diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..9d8dbfff8 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,54 @@ +name: Deploy to Github Pages + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Cache Hugo resources + uses: actions/cache@v2 + env: + cache-name: cache-hugo-resources + with: + path: resources + key: ${{ env.cache-name }} + + - uses: actions/setup-go@v2 + with: + go-version: "^1.17.0" + - run: go version + + - name: Cache Go Modules + uses: actions/cache@v2 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Setup Hugo + uses: peaceiris/actions-hugo@v2 + with: + hugo-version: "latest" + extended: true + + - name: Build + run: hugo --minify --gc + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.1.4 + with: + branch: gh-pages + folder: public + clean: true + single-commit: true diff --git a/.github/workflows/update-theme.yml b/.github/workflows/update-theme.yml new file mode 100644 index 000000000..9d3a521b4 --- /dev/null +++ b/.github/workflows/update-theme.yml @@ -0,0 +1,33 @@ +name: Update theme + +# Controls when the workflow will run +on: + schedule: + # Update theme automatically everyday at 00:00 UTC + - cron: "0 0 * * *" + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Hugo + uses: peaceiris/actions-hugo@v2 + with: + hugo-version: "latest" + extended: true + + - name: Update theme + run: hugo mod get -u github.com/CaiJimmy/hugo-theme-stack/v3 + + - name: Tidy go.mod, go.sum + run: hugo mod tidy + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "CI: Update theme" diff --git a/404.html b/404.html new file mode 100644 index 000000000..b7ee7f802 --- /dev/null +++ b/404.html @@ -0,0 +1,16 @@ +404 Page not found +

Not Found

This page does not exist

\ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..abc5e836f --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +kurisaw.eu.org \ No newline at end of file diff --git a/about/index.html b/about/index.html new file mode 100644 index 000000000..0acacd50b --- /dev/null +++ b/about/index.html @@ -0,0 +1,37 @@ +About +

About

+

Hi there!👋

I’m KurisaW,or you can call me yifang.

1
+2
+3
+4
+5
+6
+7
+
🔭 Now I am a junior student ...
+🌱 I’m currently learning RT-Thread、linux、ROS ...
+👯 I’m looking to collaborate on Embedded or neural network ...
+🤔 I'm looking forward to sharing my experience and learning to help some beginners get through the rookie phase faster ...
+💬 Ask me about Linux、Embedded ...
+
+😊 I will be happy to discuss technology and knowledge with you and look forward to your visit!
+

Contact me:

You can also choose to get in touch with me by adding wechat!

Wechat

+Licensed under CC BY-NC-SA 4.0
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git a/archives/index.html b/archives/index.html new file mode 100644 index 000000000..1ecf8bb8b --- /dev/null +++ b/archives/index.html @@ -0,0 +1,16 @@ +Archives +

Categories

2023

\ No newline at end of file diff --git a/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e.jpg b/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e.jpg new file mode 100644 index 000000000..2aa0832d0 Binary files /dev/null and b/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e.jpg differ diff --git a/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e_hu1027588b9ea4846d035dad04ea40ceac_5833_250x150_fill_q75_box_smart1.jpg b/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e_hu1027588b9ea4846d035dad04ea40ceac_5833_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..23f61defa Binary files /dev/null and b/categories/cplusplus/index.1dde93ee982a6894807d7be9ca55344e_hu1027588b9ea4846d035dad04ea40ceac_5833_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/cplusplus/index.html b/categories/cplusplus/index.html new file mode 100644 index 000000000..926609cb5 --- /dev/null +++ b/categories/cplusplus/index.html @@ -0,0 +1,55 @@ +Category: Cplusplus - kurisaW +

Categories

1 page

Cplusplus

C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:抽象、封装、继承和多态。

\ No newline at end of file diff --git a/categories/cplusplus/index.jpg b/categories/cplusplus/index.jpg new file mode 100644 index 000000000..2aa0832d0 Binary files /dev/null and b/categories/cplusplus/index.jpg differ diff --git a/categories/cplusplus/index.xml b/categories/cplusplus/index.xml new file mode 100644 index 000000000..b81e63d61 --- /dev/null +++ b/categories/cplusplus/index.xml @@ -0,0 +1,856 @@ +Cplusplus on kurisaWhttps://kurisaw.github.io/categories/cplusplus/Recent content in Cplusplus on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git a/categories/cplusplus/index_hu1027588b9ea4846d035dad04ea40ceac_5833_120x120_fill_q75_box_smart1.jpg b/categories/cplusplus/index_hu1027588b9ea4846d035dad04ea40ceac_5833_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..e33e444d3 Binary files /dev/null and b/categories/cplusplus/index_hu1027588b9ea4846d035dad04ea40ceac_5833_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/cplusplus/page/1/index.html b/categories/cplusplus/page/1/index.html new file mode 100644 index 000000000..287540252 --- /dev/null +++ b/categories/cplusplus/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/cplusplus/ + \ No newline at end of file diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477.jpg" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477.jpg" new file mode 100644 index 000000000..c565e5094 Binary files /dev/null and "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477.jpg" differ diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_250x150_fill_q75_box_smart1.jpg" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..961acce5c Binary files /dev/null and "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.cdafc8ba692969600b8569a839b64477_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.html" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.html" new file mode 100644 index 000000000..b888f4741 --- /dev/null +++ "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.html" @@ -0,0 +1,55 @@ +Category: C素养提升 - kurisaW +

Categories

2 pages

C素养提升

C是一种通用的、过程式编程编程语言,支持结构化编程、词法作用域和递归,使用静态类型系统,并且广泛用于系统软件与应用软件的开发。该专栏主要用于记录个人c语言学习笔记。

\ No newline at end of file diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" new file mode 100644 index 000000000..c565e5094 Binary files /dev/null and "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" differ diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" new file mode 100644 index 000000000..f85707c56 --- /dev/null +++ "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" @@ -0,0 +1,1843 @@ +C素养提升 on kurisaWhttps://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/Recent content in C素养提升 on kurisaWHugo -- gohugo.ioenSun, 29 Aug 2021 00:00:00 +0000C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p> \ No newline at end of file diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_120x120_fill_q75_box_smart1.jpg" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..5f240e98f Binary files /dev/null and "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/index_hu4c97bbc8cda6aa16bc34c660d62a1c66_475441_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" new file mode 100644 index 000000000..93b2f0d5e --- /dev/null +++ "b/categories/c\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/ + \ No newline at end of file diff --git a/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762.jpg b/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762.jpg new file mode 100644 index 000000000..b55198d32 Binary files /dev/null and b/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762.jpg differ diff --git a/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762_hua71f1d51f8cef626457703f12ef4d975_85805_250x150_fill_q75_box_smart1.jpg b/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762_hua71f1d51f8cef626457703f12ef4d975_85805_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..9b92bbed3 Binary files /dev/null and b/categories/experience_sharing/index.175f70f5cda933bdb2f3508a8a20b762_hua71f1d51f8cef626457703f12ef4d975_85805_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/experience_sharing/index.html b/categories/experience_sharing/index.html new file mode 100644 index 000000000..6c23d7e7a --- /dev/null +++ b/categories/experience_sharing/index.html @@ -0,0 +1,56 @@ +Category: experience_sharing - kurisaW +

Categories

8 pages

experience_sharing

Here I will share some of the problems encountered in the development of the project and provide solutions and tips for stomping holes.

\ No newline at end of file diff --git a/categories/experience_sharing/index.jpg b/categories/experience_sharing/index.jpg new file mode 100644 index 000000000..b55198d32 Binary files /dev/null and b/categories/experience_sharing/index.jpg differ diff --git a/categories/experience_sharing/index.xml b/categories/experience_sharing/index.xml new file mode 100644 index 000000000..a8c75faf5 --- /dev/null +++ b/categories/experience_sharing/index.xml @@ -0,0 +1,1371 @@ +experience_sharing on kurisaWhttps://kurisaw.github.io/categories/experience_sharing/Recent content in experience_sharing on kurisaWHugo -- gohugo.ioenSat, 03 Feb 2024 15:00:00 +0000【经验分享】如何让你的终端实现自动补齐、历史回溯https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/cover.jpg" alt="Featured image of post 【经验分享】如何让你的终端实现自动补齐、历史回溯" /><h2 id="linux下配置">Linux下配置 +</h2><p>在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:</p> +<h3 id="步骤-1-安装-zsh">步骤 1: 安装 zsh +</h3><p>确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install zsh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-2-安装-oh-my-zsh">步骤 2: 安装 oh-my-zsh +</h3><p>在终端中运行以下命令来安装 oh-my-zsh:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者,如果你没有安装 <code>curl</code>,可以使用 <code>wget</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-3-更改主题">步骤 3: 更改主题 +</h3><ol> +<li> +<p>打开 <code>~/.zshrc</code> 文件以编辑它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nano ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>找到 <code>ZSH_THEME</code> 行并更改主题。你可以在 <a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" target="_blank" rel="noopener" +>oh-my-zsh 主题库</a>中选择一个主题,例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">ZSH_THEME</span><span class="o">=</span><span class="s2">&#34;agnoster&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>保存并关闭文件。</p> +</li> +</ol> +<h3 id="步骤-4-启用历史回溯">步骤 4: 启用历史回溯 +</h3><p>oh-my-zsh 默认启用历史回溯。确保 <code>~/.zshrc</code> 中没有明确禁用该功能的设置。检查是否存在以下行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;yyyy-mm-dd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-5-重新启动-zsh-或打开新终端">步骤 5: 重新启动 zsh 或打开新终端 +</h3><p>在更改 <code>~/.zshrc</code> 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 <code>zsh</code> 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。</p> +<h2 id="windwos下配置">Windwos下配置 +</h2><p>在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 <code>PSReadLine</code> 模块,它提供了丰富的命令行编辑和历史记录功能。</p> +<p>以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:</p> +<ol> +<li> +<p><strong>安装 PSReadLine 模块:</strong> +打开 PowerShell 终端,并执行以下命令来安装 <code>PSReadLine</code> 模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">PSReadLine</span> <span class="n">-Force</span> <span class="n">-SkipPublisherCheck</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>配置 PowerShell 用户配置文件:</strong> +执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">notepad</span> <span class="nv">$PROFILE</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>在配置文件中添加以下行:</strong> +在打开的配置文件中,添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Import-Module</span> <span class="n">PSReadLine</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-HistoryNoDuplicates:</span><span class="vm">$false</span> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-EditMode</span> <span class="n">Emacs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存并关闭文件。</p> +</li> +<li> +<p><strong>重新启动 PowerShell:</strong> +关闭当前的 PowerShell 终端,并重新打开一个新的终端。</p> +</li> +<li> +<p><strong>使用历史记录搜索:</strong> +可以在 PowerShell 终端中使用 <code>Ctrl + r</code> 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。</p> +</li> +</ol>【经验分享】WSL中使用USB设备https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【经验分享】WSL中使用USB设备" /><h2 id="具体步骤">具体步骤: +</h2><p>首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:</p> +<blockquote> +<p>下载链接:https://github.com/dorssel/usbipd-win/releases</p> +</blockquote> +<p>同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开wsl ubuntu终端使用命令:<code>uname -r</code>得到版本号,同时根据版本号使用管理员模式新建目录</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7.png" +width="587" +height="103" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="569" +data-flex-basis="1367px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases</p> +<p>这里的版本就是你使用命令 <code>uname -r</code> 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下</p> +<p>然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl">$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ <span class="o">&amp;&amp;</span> sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后将内核的一些配置信息复制到当前文件夹下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp /proc/config.gz config.gz +</span></span><span class="line"><span class="cl">$ sudo gunzip config.gz +</span></span><span class="line"><span class="cl">$ sudo mv config .config +</span></span></code></pre></td></tr></table> +</div> +</div><p>接着我们执行menuconfig命令打开图形化菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入如下路径:<code>&gt; Device Drivers &gt; USB support</code></p> +<p>下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Device Drivers -&gt; USB Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB announce new devices +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB Modem <span class="o">(</span>CDC ACM<span class="o">)</span> support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; VHCI HCD +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support -&gt; USB FTDI Single port Serial Driver +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时记得关闭 <code>Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; Debug messages for USB/IP</code>这一选项,否则调试信息会非常影响你的使用体验</p> +<p>另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>内核编译期间发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" +width="1069" +height="344" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="310" +data-flex-basis="745px" +></p> +<p>这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install dwarves +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo make -j8 <span class="o">&amp;&amp;</span> sudo make modules_install -j8 <span class="o">&amp;&amp;</span> sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现又产生了报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac.png" +width="932" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="300" +data-flex-basis="721px" +></p> +<p>查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo vi .config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装内核时发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png.webp" +width="1200" +height="176" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="681" +data-flex-basis="1636px" +></p> +<p>解决方式有两种:</p> +<ul> +<li>1.可以选择在<code>.config</code>中禁用宏<code>CONFIG_X86_X32</code></li> +<li>2.找到合适的binutils版本使其能够编译</li> +</ul> +<p>我选择的是第一种,根据我在网上找到的说法是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>所以我选择禁用宏<code>CONFIG_X86_X32</code>,之后继续执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make modules_install -j8 +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>之后就可以选择编译 USBIP 工具了:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> tools/usb/usbip +</span></span><span class="line"><span class="cl">$ sudo ./autogen.sh +</span></span><span class="line"><span class="cl">$ sudo ./configure +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>复制工具库位置,以便 usbip 工具可以获取到:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装 usb.ids 以便显示 USB 设备的名称:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt-get install hwdata +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启WSL:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ wsl --shutdown +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面进行测试是否成功: +打开powershell:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl list +</span></span></code></pre></td></tr></table> +</div> +</div><p>假设我们需要在wsl使用的 usb 设备为 <code>ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3)</code>,设备id为 <code>0483:374b</code></p> +<p>我们使用命令附加设备到 wsl2 中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;0483:374b&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" +width="1200" +height="408" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="294" +data-flex-basis="705px" +></p> +<p>此时我们打开一个 wsl 终端,使用命令 <code>lsusb</code> 即可看到附加到 wsl 的设备</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96.png" +width="1146" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="369" +data-flex-basis="887px" +></p> +<p>然后我们再次回到 powershell ,执行 <code>usbipd wsl list</code>命令,可以看到此时的 usb 设备已经成功添加到 wsl 了</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" +width="1200" +height="572" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="209" +data-flex-basis="503px" +></p>【经验分享】Linux环境下v2ray的使用https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/cover.jpg" alt="Featured image of post 【经验分享】Linux环境下v2ray的使用" /><h1 id="linux-环境下v2ray的使用">Linux 环境下v2ray的使用 +</h1><hr> +<blockquote> +<p>v2ray官方文档:<a class="link" href="https://v2raya.org/" target="_blank" rel="noopener" +>https://v2raya.org/</a></p> +</blockquote> +<h2 id="curl安装">curl安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">apt-get purge libcurl4 +</span></span><span class="line"><span class="cl">apt-get install curl +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray镜像脚本安装">v2ray镜像脚本安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">curl</span> <span class="o">-</span><span class="n">Ls</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.v2raya.org/go.sh | sudo bash +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041040498.png" +loading="lazy" +alt="image-20230504104013149" +></p> +<p>出现该提示信息则表示安装成功:<code>info: V2Ray v5.4.1 is installed.</code></p> +<p>接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">disable</span> <span class="n">v2ray</span> <span class="o">--</span><span class="n">now</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray软件安装">v2ray软件安装 +</h2><blockquote> +<p>仓库release地址:<a class="link" href="https://github.com/v2rayA/v2rayA/releases" target="_blank" rel="noopener" +>https://github.com/v2rayA/v2rayA/releases</a></p> +</blockquote> +<p>选择合适自己 Linux 内核架构,可以使用<code>dpkg --print-architecture</code>查看</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041050162.png" +loading="lazy" +alt="image-20230504105029122" +></p> +<p>这里我选择``下载到 Linux 共享文件夹</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041052416.png" +loading="lazy" +alt="image-20230504105226313" +></p> +<p>将共享文件夹下的<code>installer_debian_amd64_2.0.5.deb</code>文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041054352.png" +loading="lazy" +alt="image-20230504105440300" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041053522.png" +loading="lazy" +alt="image-20230504105340371" +></p> +<h2 id="启动v2raya进程">启动v2raya进程 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">start</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="设置开机自启动">设置开机自启动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">enable</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray使用">v2ray使用 +</h2><p>打开火狐浏览器,输入 http://localhost:2017/</p> +<p>输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041058629.png" +loading="lazy" +alt="image-20230504105825544" +></p> +<p>导入我们的机场订阅地址</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041100916.png" +loading="lazy" +alt="image-20230504105925321" +></p> +<p>选择想要使用的节点后,点击 Ready</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041106172.png" +loading="lazy" +alt="image-20230504110635073" +></p> +<h2 id="v2ray-settings">v2ray Settings +</h2><p>我们点击网页上右上角的Setting,进行如下修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041110129.png" +loading="lazy" +alt="image-20230504111011073" +></p> +<h2 id="测试">测试 +</h2><p>至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041111183.png" +loading="lazy" +alt="image-20230504111116983" +></p>Wireshark网络抓包教程https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover.jpg" alt="Featured image of post Wireshark网络抓包教程" /><blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/HarveyH/article/details/113731485" target="_blank" rel="noopener" +>转自:WireShark 抓包使用教程&ndash;详细</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:</p> +<p>1、Wireshark软件下载和安装以及Wireshark主界面介绍。</p> +<p>2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。</p> +<p>3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。</p> +<h2 id="wireshark软件安装">Wireshark软件安装 +</h2><p>软件下载路径:<a class="link" href="https://www.wireshark.org/" target="_blank" rel="noopener" +>wireshark官网</a>。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。</p> +<p>如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:<a class="link" href="http://www.win10pcap.org/download/" target="_blank" rel="noopener" +>win10pcap兼容性安装包</a></p> +<h2 id="wireshark-开始抓包示例"><strong>Wireshark 开始抓包示例</strong> +</h2><p>先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。</p> +<p>1、打开wireshark 2.6.5,主界面如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102042369.png" +loading="lazy" +alt="image-20230410204240214" +></p> +<p>2、选择菜单栏上Capture -&gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043634.png" +loading="lazy" +alt="image-20230410204301558" +></p> +<p>3、wireshark启动后,wireshark处于抓包状态中。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043120.png" +loading="lazy" +alt="image-20230410204330881" +></p> +<p>4、执行需要抓包的操作,如ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>。</p> +<p>5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043973.png" +loading="lazy" +alt="image-20230410204349768" +></p> +<p>5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。</p> +<h2 id="wireshakr抓包界面">Wireshakr抓包界面 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044121.png" +loading="lazy" +alt="image-20230410204417023" +></p> +<p>说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --&gt; Coloring Rules。如下所示</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044221.png" +loading="lazy" +alt="image-20230410204435065" +></p> +<p><strong>WireShark 主要分为这几个界面</strong></p> +<p>1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --&gt; Display Filters。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045496.png" +loading="lazy" +alt="image-20230410204500320" +></p> +<p>2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045343.png" +loading="lazy" +alt="image-20230410204525166" +></p> +<p>3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为</p> +<p>(1)Frame: 物理层的数据帧概况</p> +<p>(2)Ethernet II: 数据链路层以太网帧头部信息</p> +<p>(3)Internet Protocol Version 4: 互联网层IP包头部信息</p> +<p>(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP</p> +<p>(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045382.png" +loading="lazy" +alt="image-20230410204540297" +></p> +<p><strong>TCP包的具体内容</strong></p> +<p>从下图可以看到wireshark捕获到的TCP包中的每个字段。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045329.png" +loading="lazy" +alt="image-20230410204557194" +></p> +<p>4. Dissector Pane(数据包字节区)。</p> +<h2 id="wireshark过滤器设置">Wireshark过滤器设置 +</h2><p>初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。</p> +<p>(1)抓包过滤器</p> +<p>捕获过滤器的菜单栏路径为Capture --&gt; Capture Filters。用于<strong>在抓取数据包前设置。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046204.png" +loading="lazy" +alt="image-20230410204620124" +></p> +<p>如何使用?可以在抓取数据包前设置如下。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046995.png" +loading="lazy" +alt="image-20230410204653927" +></p> +<p>ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047470.png" +loading="lazy" +alt="image-20230410204717268" +></p> +<p>(2)显示过滤器</p> +<p>显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047185.png" +loading="lazy" +alt="image-20230410204734985" +></p> +<p>执行ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取的数据包列表如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047584.png" +loading="lazy" +alt="image-20230410204753507" +></p> +<p>观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048361.png" +loading="lazy" +alt="image-20230410204815301" +></p> +<p>上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。</p> +<p><strong>wireshark过滤器表达式的规则</strong></p> +<p>1、抓包过滤器语法和实例</p> +<p>抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&amp;&amp; 与、|| 或、!非)</p> +<p>(1)协议过滤</p> +<p>比较简单,直接在抓包过滤框中直接输入协议名即可。</p> +<p>TCP,只显示TCP协议的数据包列表</p> +<p>HTTP,只查看HTTP协议的数据包列表</p> +<p>ICMP,只显示ICMP协议的数据包列表</p> +<p>(2)IP过滤</p> +<p>host 192.168.1.104</p> +<p>src host 192.168.1.104</p> +<p>dst host 192.168.1.104</p> +<p>(3)端口过滤</p> +<p>port 80</p> +<p>src port 80</p> +<p>dst port 80</p> +<p>(4)逻辑运算符&amp;&amp; 与、|| 或、!非</p> +<p>src host 192.168.1.104 &amp;&amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包</p> +<p>host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包</p> +<p>!broadcast 不抓取广播数据包</p> +<p>2、显示过滤器语法和实例</p> +<p>(1)比较操作符</p> +<p>比较操作符有== 等于、!= 不等于、&gt; 大于、&lt; 小于、&gt;= 大于等于、&lt;=小于等于。</p> +<p>(2)协议过滤</p> +<p>比较简单,直接在Filter框中直接输入协议名即可。<strong>注意:协议名称需要输入小写。</strong></p> +<p>tcp,只显示TCP协议的数据包列表</p> +<p>http,只查看HTTP协议的数据包列表</p> +<p>icmp,只显示ICMP协议的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048252.png" +loading="lazy" +alt="image-20230410204852057" +></p> +<p>(3) ip过滤</p> +<p>ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表</p> +<p>ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表</p> +<p>ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049772.png" +loading="lazy" +alt="image-20230410204937591" +></p> +<p>(4)端口过滤</p> +<p>tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。</p> +<p>tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。</p> +<p>tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049752.png" +loading="lazy" +alt="image-20230410204953546" +></p> +<p>(5) Http模式过滤</p> +<p>http.request.method==&ldquo;GET&rdquo;, 只显示HTTP GET方法的。</p> +<p>(6)逻辑运算符为 and/or/not</p> +<p>过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050123.png" +loading="lazy" +alt="image-20230410205019907" +></p> +<p>(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050553.png" +loading="lazy" +alt="image-20230410205039366" +></p> +<p>右键单击选中后出现如下界面</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050685.png" +loading="lazy" +alt="image-20230410205054595" +></p> +<p>选中Select后在过滤器中显示如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051573.png" +loading="lazy" +alt="image-20230410205109402" +></p> +<p>后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含&quot;abcd&quot;内容的数据流。<strong>包含的关键词是contains 后面跟上内容。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051902.png" +loading="lazy" +alt="image-20230410205121718" +></p> +<p>看到这, 基本上对wireshak有了初步了解。</p> +<h2 id="wireshark抓包分析tcp三次握手">Wireshark抓包分析TCP三次握手 +</h2><p>(1)TCP三次握手连接建立过程</p> +<p>Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;</p> +<p>Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;</p> +<p>Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051845.png" +loading="lazy" +alt="image-20230410205135665" +></p> +<p>(2)wireshark抓包获取访问指定服务端数据包</p> +<p>Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。</p> +<p>Step2:使用ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取IP。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051433.png" +loading="lazy" +alt="image-20230410205150253" +></p> +<p>Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052925.png" +loading="lazy" +alt="image-20230410205200760" +></p> +<p>图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。</p> +<p><strong>第一次握手数据包</strong></p> +<p>客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052226.png" +loading="lazy" +alt="image-20230410205215079" +></p> +<p>数据包的关键属性如下:</p> +<p>SYN :标志位,表示请求建立连接</p> +<p>Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据</p> +<p>Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据</p> +<p><strong>第二次握手的数据包</strong></p> +<p>服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052307.png" +loading="lazy" +alt="image-20230410205230236" +></p> +<p>数据包的关键属性如下:</p> +<p>[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK</p> +<p>Seq = 0 :初始建立值为0,表示当前还没有发送数据</p> +<p>Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)</p> +<p><strong>第三次握手的数据包</strong></p> +<p>客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052080.png" +loading="lazy" +alt="image-20230410205245006" +></p> +<p>数据包的关键属性如下:</p> +<p>ACK :标志位,表示已经收到记录</p> +<p>Seq = 1 :表示当前已经发送1个数据</p> +<p>Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。</p> +<p>就这样通过了TCP三次握手,建立了连接。开始进行数据交互</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053540.png" +loading="lazy" +alt="image-20230410205305433" +></p> +<p>下面针对数据交互过程的数据包进行一些说明:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053537.png" +loading="lazy" +alt="image-20230410205320467" +></p> +<p>数据包的关键属性说明</p> +<p>Seq: 1</p> +<p>Ack: 1: 说明现在共收到1字节数据</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053985.png" +loading="lazy" +alt="image-20230410205335911" +></p> +<p>Seq: 1<br> +Ack: 951: 说明现在服务端共收到951字节数据</p> +<p>在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053340.png" +loading="lazy" +alt="image-20230410205349152" +></p> +<p>其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。</p> +<h2 id="wireshark分析常用操作">Wireshark分析常用操作 +</h2><p>调整数据包列表中时间戳显示格式。调整方法为View --&gt;Time Display Format --&gt; Date and Time of Day。调整后格式如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102054848.png" +loading="lazy" +alt="image-20230410205401641" +></p>【经验分享】ARM常用汇编指令https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/Wed, 29 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/cover.jpg" alt="Featured image of post 【经验分享】ARM常用汇编指令" /><h1 id="arm常用汇编指令">ARM常用汇编指令 +</h1><table> +<thead> +<tr> +<th>指令名称</th> +<th>作用</th> +</tr> +</thead> +<tbody> +<tr> +<td>EQU</td> +<td>给数字常量设置一个符号名,相当于C语言中的define</td> +</tr> +<tr> +<td>AREA</td> +<td>汇编一个新的代码段或者数据段</td> +</tr> +<tr> +<td>SPACE</td> +<td>分配内存空间</td> +</tr> +<tr> +<td>PRESERVE8</td> +<td>当前文件栈需要按照8字节对齐</td> +</tr> +<tr> +<td>EXPORT</td> +<td>声明一个符号具有全局属性,可被外部文件使用</td> +</tr> +<tr> +<td>DCD</td> +<td>以字为单位分配内存,要求4字节对齐,并要求初始化这些内存</td> +</tr> +<tr> +<td>PROC</td> +<td>定义子程序,与ENDP成对使用,表示子程序结束</td> +</tr> +<tr> +<td>WEAK</td> +<td>弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>IMPORT</td> +<td>声明标号来自外部文件,与C语言的EXETERN关键字类似</td> +</tr> +<tr> +<td>B</td> +<td>跳转到一个标号</td> +</tr> +<tr> +<td>ALIGN</td> +<td>编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>END</td> +<td>到达文件的末尾,文件结束</td> +</tr> +<tr> +<td>IF,ELSE,ENDIF</td> +<td>汇编条件分支语句,与C语言的if else类似</td> +</tr> +<tr> +<td>MRS</td> +<td>加载特殊功能寄存器的值到特殊功能寄存器</td> +</tr> +<tr> +<td>CBZ</td> +<td>比较,如果结果为0则转移</td> +</tr> +<tr> +<td>CBNZ</td> +<td>比较,如果结果非0则转移</td> +</tr> +<tr> +<td>LDR</td> +<td>从存储器中加载字到一个寄存器中</td> +</tr> +<tr> +<td>LDR[伪指令]</td> +<td>加载一个立即数或者一个地址到一个寄存器中。</td> +</tr> +<tr> +<td>LDRH</td> +<td>从存储器中加载半字到一个寄存器中</td> +</tr> +<tr> +<td>LDRB</td> +<td>从存储器中加载字节到一个寄存器中</td> +</tr> +<tr> +<td>STR</td> +<td>把一个寄存器按字节存储到存储器中</td> +</tr> +<tr> +<td>STRH</td> +<td>把一个寄存器的低半字存储到存储器中</td> +</tr> +<tr> +<td>STRB</td> +<td>把一个寄存器的低字节存储到存储器中</td> +</tr> +<tr> +<td>LDMIA</td> +<td>加载多个字,并且在加载后自增基址寄存器</td> +</tr> +<tr> +<td>STMIA</td> +<td>存储多个字,并且在存储后自增基址寄存器</td> +</tr> +<tr> +<td>ORR</td> +<td>按位或</td> +</tr> +<tr> +<td>BX</td> +<td>直接跳转到由寄存器给定的地址</td> +</tr> +<tr> +<td>BL</td> +<td>跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR</td> +</tr> +<tr> +<td>BLX</td> +<td>跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错</td> +</tr> +</tbody> +</table>RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p>Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/Tue, 12 Apr 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/cover.jpg" alt="Featured image of post Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)" /><h2 id="1microsoft-visual-c-140安装">1、Microsoft Visual C++ 14.0安装 +</h2><p>这里附上百度网盘下载链接: +链接: <a class="link" href="https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88</a> 提取码: ec88</p> +<p>下载完成后双击打开 +<img src="https://img-blog.csdnimg.cn/04150c3c158c4baab13f0646ab6bb578.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>默认下载方式即可</p> +<hr> +<h2 id="2pycocotools20版本安装">2、Pycocotools2.0版本安装 +</h2><h4 id="1准备材料">(1)准备材料: +</h4><ul> +<li><a class="link" href="https://github.com/cocodataset/cocoapi" target="_blank" rel="noopener" +>下载pycocotools安装包</a>(可直接git拉取到本地文件夹)</li> +</ul> +<h4 id="2源码配置">(2)源码配置 +</h4><p>打开下载好的pycocotools,双击打开<code>setup.py</code>(文件路径:\cocoapi\PythonAPI\setup.py)</p> +<p><img src="https://img-blog.csdnimg.cn/985a37a42b1043bc9dc87d3c3e4e1d0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这里<code>将蓝色部分删除,只保留红色部分</code>(切记需要执行这一步!!!)</p> +<p>开始界面找到所有应用并打开<code>Anaconda Powershell Prompt</code></p> +<p><img src="https://img-blog.csdnimg.cn/9ad6e210127c49c9bfb16f9fd9b65968.png" +loading="lazy" +></p> +<p>先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。</p> +<p>如上图所示进入到<code>\cocoapi\PythonAPI</code>该目录下</p> +<p>分别执行以下两个命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="o">--</span><span class="n">inplace</span> +</span></span><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="n">install</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/02ec23e44b3848609cc74c8c28368a0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>执行pip list查看</p> +<p><img src="https://img-blog.csdnimg.cn/642adca979d64daba7f8d2164e88443c.png" +loading="lazy" +> +此时回到<code>\cocoapi\PythonAPI</code>目录下,可以看到生成了相关文件 +<img src="https://img-blog.csdnimg.cn/bdde5563cb794cf1962800f4656b71f5.png" +loading="lazy" +alt="在这里插入图片描述" +> +将<code>pycocotools</code>和<code>pycocotools.egg-info</code>文件夹复制到你所创建的虚拟环境中(位置:Anaconda3-&gt;envs-&gt;python_env-&gt;Lib-&gt;site-packages) +<img src="https://img-blog.csdnimg.cn/8dd05ee9c4724de4a2ba536ad84aec81.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>至此所有问题解决!</p>总结:开发板挂载根文件系统遇到的一些问题https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/Wed, 30 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/cover.jpg" alt="Featured image of post 总结:开发板挂载根文件系统遇到的一些问题" /><h2 id="一桥接网络">一、桥接网络 +</h2><h4 id="1简介">1、简介 +</h4><p>是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址</p> +<h4 id="注意避坑">注意避坑: +</h4><p>如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。</p> +<h4 id="2解决办法">2、解决办法: +</h4><p>&lt;1&gt;选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241318456.png" +loading="lazy" +alt="image-20230424131854375" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241319850.png" +loading="lazy" +alt="image-20230424131957782" +></p> +<p>&lt;2&gt;无线网卡连接</p> +<p>考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)</p> +<p>如下配置:</p> +<ul> +<li>主机配置</li> +</ul> +<p>首先电脑win+R,输入<code>cmd</code>进入终端,然后输入命令:<code>ipconfig</code>,找到自己的热点网络信息</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320409.png" +loading="lazy" +alt="image-20230424132028276" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320692.png" +loading="lazy" +alt="image-20230424132041431" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241321679.png" +loading="lazy" +alt="image-20230424132117501" +></p> +<ul> +<li>虚拟机配置</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322849.png" +loading="lazy" +alt="image-20230424132214739" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322385.png" +loading="lazy" +alt="image-20230424132233318" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322519.png" +loading="lazy" +alt="image-20230424132250210" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">保存退出后,再次输入命令: +</span></span><span class="line"><span class="cl">首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡) +</span></span><span class="line"><span class="cl">然后启用网卡:ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="二开发板端测试">二、开发板端测试: +</h2><p><code>以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客</code></p> +<p><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124407302?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【Linux系统开发】x210开发板根目录文件系统构建</a></p> +<p>我们打开secureCRT:</p> +<p>开机先ping下虚拟机网络:<code>ping '虚拟机IP'</code></p> +<blockquote> +<p>注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="err">方法一:打开命令:</span><span class="n">sudo</span> <span class="n">gedit</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">NetworkManager</span><span class="o">/</span><span class="n">nm</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">settings</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">出现文件内容:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># This file is installed into /etc/NetworkManager, and is loaded by</span> +</span></span><span class="line"><span class="cl"><span class="c1"># NetworkManager by default. To override, specify: &#39;--config file&#39;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># during NM startup. This can be done by appending to DAEMON_OPTS in</span> +</span></span><span class="line"><span class="cl"><span class="c1"># the file:</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"><span class="c1"># /etc/default/NetworkManager</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">main</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">plugins</span><span class="o">=</span><span class="n">ifupdown</span><span class="p">,</span><span class="n">keyfile</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">ifupdown</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">managed</span><span class="o">=</span><span class="bp">true</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">(这里</span><span class="n">false改成true</span><span class="err">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">方法二:虚拟机重置网卡 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ifdown eth0 +</span></span><span class="line"><span class="cl">ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>当开发板ping通虚拟机后,我们在secureCRT控制台输入<code>reset</code>命令重启开发板</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323671.png" +loading="lazy" +alt="image-20230424132308595" +></p> +<p>这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323776.png" +loading="lazy" +alt="image-20230424132323723" +></p> +<p>解决:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mount -t nfs -o nolock &#39;开发板ipaddr ip&#39;:/root/rootfs/x210_rootfs //再次重新挂载根文件系统 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//NFC网络重启 +</span></span><span class="line"><span class="cl">/etc/init.d/nfs-kernel-server restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323050.png" +loading="lazy" +alt="image-20230424132335917" +></p> +<p>问题解决!</p> \ No newline at end of file diff --git a/categories/experience_sharing/index_hua71f1d51f8cef626457703f12ef4d975_85805_120x120_fill_q75_box_smart1.jpg b/categories/experience_sharing/index_hua71f1d51f8cef626457703f12ef4d975_85805_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..237ecf687 Binary files /dev/null and b/categories/experience_sharing/index_hua71f1d51f8cef626457703f12ef4d975_85805_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/experience_sharing/page/1/index.html b/categories/experience_sharing/page/1/index.html new file mode 100644 index 000000000..2f2250536 --- /dev/null +++ b/categories/experience_sharing/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/experience_sharing/ + \ No newline at end of file diff --git a/categories/experience_sharing/page/2/index.html b/categories/experience_sharing/page/2/index.html new file mode 100644 index 000000000..e251f72e9 --- /dev/null +++ b/categories/experience_sharing/page/2/index.html @@ -0,0 +1,56 @@ +Category: experience_sharing - Pager 2 - kurisaW +

Categories

8 pages

experience_sharing

Here I will share some of the problems encountered in the development of the project and provide solutions and tips for stomping holes.

\ No newline at end of file diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921.jpg" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921.jpg" new file mode 100644 index 000000000..5b799e6f3 Binary files /dev/null and "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921.jpg" differ diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921_hu344c1fa4f15fd328833362988690574d_18346_250x150_fill_q75_box_smart1.jpg" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921_hu344c1fa4f15fd328833362988690574d_18346_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..de09a9d1f Binary files /dev/null and "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.b65e042d330ca4c57cdbdac234e34921_hu344c1fa4f15fd328833362988690574d_18346_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.html" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.html" new file mode 100644 index 000000000..df9d55e51 --- /dev/null +++ "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.html" @@ -0,0 +1,56 @@ +Category: Git版本控制 - kurisaW +

Categories

6 pages

Git版本控制

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。

\ No newline at end of file diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.jpg" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.jpg" new file mode 100644 index 000000000..5b799e6f3 Binary files /dev/null and "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.jpg" differ diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.xml" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.xml" new file mode 100644 index 000000000..3078844e4 --- /dev/null +++ "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index.xml" @@ -0,0 +1,1651 @@ +Git版本控制 on kurisaWhttps://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Recent content in Git版本控制 on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Git版本控制】Github和Gitlab同时使用sshhttps://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover.jpg" alt="Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh" /><h2 id="前言">前言 +</h2><p>最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下</p> +<h2 id="本地生成公私密钥">本地生成公私密钥 +</h2><p>首先确保把之前的 ssh 信息清除,也可以将整个 <code>~/.ssh</code> 目录删除</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rm -rf ~/.ssh/* +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们分别生成 Github 和 Gitlab账号的 SSH 密钥</p> +<ul> +<li>Github 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意不要选择其他操作,一路回车即可</p> +<p>此时打开 <code>~/.ssh/</code> 目录可以看到生成了四个文件:<code>github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub</code></p> +<p>其中 <code>.pub</code> 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存</p> +<h2 id="远程仓库-ssh-填写公钥密钥">远程仓库 SSH 填写公钥密钥 +</h2><p>我们先打开 Github 的 Settings选项,然后选择 <code>SSH and GPG keys-&gt;New SSH key</code> ,<code>Title</code>可以随意拟定,<code>Key</code>需要查看刚刚的 <code>github_id-rsa.pub</code> 文件,并且复制到 Gitlab 的<code>key</code>一栏中;</p> +<p>Gitlab 的操作方式与 Github 类似,具体步骤:</p> +<p>打开 <code>Gitlab -&gt; 用户设置 -&gt; SSH密钥</code> ,在密钥一栏填入 <code>gitlab_id-rsa.pub</code>文件中的具体值,标题自拟即可。</p> +<h2 id="配置不同-host-的-ssh-key">配置不同 Host 的 SSH Key +</h2><p>回到 <code>~/.ssh/</code> 目录下,并且创建一个名为 <code>config</code> 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#github</span> +</span></span><span class="line"><span class="cl">Host github.com +</span></span><span class="line"><span class="cl"> Hostname ssh.github.com +</span></span><span class="line"><span class="cl"> Port <span class="m">443</span> +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/github_id-rsa +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#gitlab</span> +</span></span><span class="line"><span class="cl">host git.rt-thread.com +</span></span><span class="line"><span class="cl"> Hostname git.rt-thread.com +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/figure/ssh-config.png" +loading="lazy" +></p> +<h2 id="验证">验证 +</h2><p>使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置</p> +<ul> +<li>Github SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@github.com +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@rt-thread.com +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功</p> +<p><img src="https://kurisaw.github.io/figure/valid-ssh.png" +loading="lazy" +></p>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p>Github同步Gitee镜像仓库自动化脚本https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/Tue, 11 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover.jpg" alt="Featured image of post Github同步Gitee镜像仓库自动化脚本" /><h1 id="github同步gitee镜像仓库自动化脚本">Github同步Gitee镜像仓库自动化脚本 +</h1><hr> +<h2 id="前言">前言 +</h2><p>在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。</p> +<h2 id="什么是hub-mirror-action">什么是Hub Mirror Action? +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111537579.png" +loading="lazy" +alt="image-20230411153729450" +></p> +<h3 id="1介绍">1.介绍 +</h3><p><a class="link" href="https://github.com/marketplace/actions/hub-mirror-action" target="_blank" rel="noopener" +>Hub Mirror Action</a>是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。</p> +<h3 id="2用法">2.用法 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Mirror the Github organization repos to Gitee.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># src_account_type: org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># dst_account_type: org</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:详细使用案例请查看官方仓库 <a class="link" href="https://github.com/Yikun/hub-mirror-action" target="_blank" rel="noopener" +>https://github.com/Yikun/hub-mirror-action</a></p> +<h2 id="配置步骤">配置步骤 +</h2><h3 id="1生成密钥对">1.生成密钥对 +</h3><p>我们先在本地使用git命令行打开终端,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ssh</span><span class="o">-</span><span class="n">keygen</span> <span class="o">-</span><span class="n">t</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">f</span> <span class="o">~/</span><span class="n">Documents</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">key</span><span class="o">/</span><span class="n">id_rsa</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注:请确保文件夹<code>~/Documents/ssh-key/</code>存在,当然你也可以选择放置在其他地方</p> +<p>过程中一路回车即可,注意不要设置密码。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111543237.png" +loading="lazy" +alt="image-20230411154330166" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111551053.png" +loading="lazy" +alt="image-20230411155124878" +></p> +<h3 id="2github私钥配置">2.GitHub私钥配置 +</h3><p>首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111547966.png" +loading="lazy" +alt="image-20230411154716849" +></p> +<ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_PRIVATE_KEY</code>的secret,值为我们之前生成的密钥对中的私钥(id_rsa)</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111553202.png" +loading="lazy" +alt="image-20230411155314101" +></p> +<h3 id="3gitee公钥配置">3.Gitee公钥配置 +</h3><p>我们打开Gitee账号,进入<code>Settings-&gt;安全设置-&gt;SSH公钥</code></p> +<p>添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111558684.png" +loading="lazy" +alt="image-20230411155846562" +></p> +<h3 id="4gitee生成私人令牌">4.Gitee生成私人令牌 +</h3><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111559999.png" +loading="lazy" +alt="image-20230411155958898" +></p> +<p>令牌名称随意,同时复制生成的令牌值。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111601466.png" +loading="lazy" +alt="image-20230411160127393" +></p> +<h3 id="5github绑定gitee令牌">5.Github绑定Gitee令牌 +</h3><ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_TOKEN</code>的secret,值为Gitee生成的令牌值</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111603849.png" +loading="lazy" +alt="image-20230411160340721" +></p> +<h3 id="6编写ci脚本">6.编写CI脚本 +</h3><p>将<code>ci_bot</code>仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="n">ci_bot</span><span class="o">/</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="p">.</span><span class="n">github</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">workflows</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">Sync</span><span class="p">.</span><span class="n">yml</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>Sync.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">push, delete, create ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出后,将本次修改push到远端仓库。</p> +<p>查看Action运行情况:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111611887.png" +loading="lazy" +alt="image-20230411161143741" +></p> +<h3 id="7多仓库同步推送">7.多仓库同步推送 +</h3><p>如果你想同时同步多个仓库,只需要完成如下修改</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">static_list 默认为&#39;&#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111633375.png" +loading="lazy" +alt="image-20230411163307283" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111631352.png" +loading="lazy" +alt="image-20230411163135259" +></p> +<h3 id="8定时运行脚本">8.定时运行脚本 +</h3><p>为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:</p> +<p>修改Sync.yml文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 0 * * *&#39;</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">delete</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">create</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111731377.png" +loading="lazy" +alt="image-20230411173142865" +></p> +<h2 id="总结">总结 +</h2><p>通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。</p>【Git版本控制】Git命令详解https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/Fri, 17 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 【Git版本控制】Git命令详解" /><h2 id="前言">前言 +</h2><p>Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 <strong>回撤</strong>这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而<strong>版本管理工具能记录每次的修改</strong>,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。</p> +<p>下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。</p> +<h2 id="展示帮助信息">展示帮助信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git help -g +</span></span></code></pre></td></tr></table> +</div> +</div><p>The command output as below:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">The common Git guides are: +</span></span><span class="line"><span class="cl"> attributes Defining attributes per path +</span></span><span class="line"><span class="cl"> cli Git command-line interface and conventions +</span></span><span class="line"><span class="cl"> core-tutorial A Git core tutorial for developers +</span></span><span class="line"><span class="cl"> cvs-migration Git for CVS users +</span></span><span class="line"><span class="cl"> diffcore Tweaking diff output +</span></span><span class="line"><span class="cl"> everyday A useful minimum set of commands for Everyday Git +</span></span><span class="line"><span class="cl"> glossary A Git Glossary +</span></span><span class="line"><span class="cl"> hooks Hooks used by Git +</span></span><span class="line"><span class="cl"> ignore Specifies intentionally untracked files to ignore +</span></span><span class="line"><span class="cl"> modules Defining submodule properties +</span></span><span class="line"><span class="cl"> namespaces Git namespaces +</span></span><span class="line"><span class="cl"> repository-layout Git Repository Layout +</span></span><span class="line"><span class="cl"> revisions Specifying revisions and ranges for Git +</span></span><span class="line"><span class="cl"> tutorial A tutorial introduction to Git +</span></span><span class="line"><span class="cl"> tutorial-2 A tutorial introduction to Git: part two +</span></span><span class="line"><span class="cl"> workflows An overview of recommended workflows with Git +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">&#39;git help -a&#39; and &#39;git help -g&#39; list available subcommands and some concept guides. See &#39;git help &lt;command&gt;&#39; or &#39;git help &lt;concept&gt;&#39; to read about a specific subcommand or concept. +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到远程仓库的状态">回到远程仓库的状态 +</h2><p>抛弃本地所有的修改,回到远程仓库的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch --all &amp;&amp; git reset --hard origin/master +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重设第一个-commit">重设第一个 commit +</h2><p>也就是把所有的改动都重新放回工作区,并<strong>清空所有的 commit</strong>,这样就可以重新提交第一个 commit 了</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-ref -d HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看冲突文件列表">查看冲突文件列表 +</h2><p>展示工作区的冲突文件列表</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --name-only --diff-filter=U +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示工作区和暂存区的不同">展示工作区和暂存区的不同 +</h2><p>输出<strong>工作区</strong>和<strong>暂存区</strong>的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff +</span></span></code></pre></td></tr></table> +</div> +</div><p>还可以展示本地仓库中任意两个 commit 之间的文件变动:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff &lt;commit-id&gt; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区和最近版本的不同">展示暂存区和最近版本的不同 +</h2><p>输出<strong>暂存区</strong>和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --cached +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区工作区和最近版本的不同">展示暂存区、工作区和最近版本的不同 +</h2><p>输出<strong>工作区</strong>、<strong>暂存区</strong> 和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="快速切换到上一个分支">快速切换到上一个分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout - +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除已经合并到-master-的分支">删除已经合并到 master 的分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch --merged master | grep -v &#39;^\*\| master&#39; | xargs -n 1 git branch -d +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示本地分支关联远程仓库的情况">展示本地分支关联远程仓库的情况 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -vv +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="关联远程分支">关联远程分支 +</h2><p>关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -u origin/mybranch +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者在 push 时加上 -u 参数</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin/mybranch -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程分支">列出所有远程分支 +</h2><p>-r 参数相当于:remote</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -r +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出本地和远程分支">列出本地和远程分支 +</h2><p>-a 参数相当于:all</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -a +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看远程分支和本地分支的对应关系">查看远程分支和本地分支的对应关系 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote show origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="远程删除了分支本地也想删除">远程删除了分支本地也想删除 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote prune origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="创建并切换到本地分支">创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程分支中创建并切换到本地分支">从远程分支中创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; origin/&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地分支">删除本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -d &lt;local-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程分支">删除远程分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete &lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin :&lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重命名本地分支">重命名本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -m &lt;new-branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签">查看标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag +</span></span></code></pre></td></tr></table> +</div> +</div><p>展示当前分支的最近的 tag</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git describe --tags --abbrev=0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签详细信息">查看标签详细信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -ln +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="本地创建标签">本地创建标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag &lt;version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ git tag -a &lt;version-number&gt; -m &#34;v1.0 发布(描述)&#34; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="推送标签到远程仓库">推送标签到远程仓库 +</h2><p>首先要保证本地创建好了标签才可以推送标签到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin &lt;local-version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>一次性推送所有标签,同步到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --tags +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地标签">删除本地标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -d &lt;tag-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程标签">删除远程标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete tag &lt;tagname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="切回到某个标签">切回到某个标签 +</h2><p>一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b branch_name tag_name +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="放弃工作区的修改">放弃工作区的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>放弃所有修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout . +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="恢复删除的文件">恢复删除的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rev-list -n 1 HEAD -- &lt;file_path&gt; #得到 deleting_commit +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git checkout &lt;deleting_commit&gt;^ -- &lt;file_path&gt; #回到删除文件 deleting_commit 之前的状态 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以新增一个-commit-的方式还原某一个-commit-的修改">以新增一个 commit 的方式还原某一个 commit 的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git revert &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-commit-的状态并删除后面的-commit">回到某个 commit 的状态,并删除后面的 commit +</h2><p>和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;commit-id&gt; #默认就是-mixed参数。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --hard &lt;commit-id&gt; #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改上一个-commit-的描述">修改上一个 commit 的描述 +</h2><p>如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看-commit-历史">查看 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看某段代码是谁写的">查看某段代码是谁写的 +</h2><p>blame 的意思为‘责怪’,你懂的。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git blame &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="显示本地更新过-head-的-git-命令记录">显示本地更新过 HEAD 的 git 命令记录 +</h2><p>每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reflog +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改作者名">修改作者名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend --author=&#39;Author Name &lt;email@address.com&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改远程仓库的-url">修改远程仓库的 url +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote set-url origin &lt;URL&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="增加远程仓库">增加远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote add origin &lt;remote-url&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程仓库">列出所有远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看两个星期内的改动">查看两个星期内的改动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git whatchanged --since=&#39;2 weeks ago&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把-a-分支的某一个-commit放到-b-分支上">把 A 分支的某一个 commit,放到 B 分支上 +</h2><p>这个过程需要 cherry-pick 命令,<a class="link" href="http://sg552.iteye.com/blog/1300713#bc2367928" target="_blank" rel="noopener" +>参考</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;branch-name&gt; &amp;&amp; git cherry-pick &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="给-git-命令起别名">给 git 命令起别名 +</h2><p>简化命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global alias.&lt;handle&gt; &lt;command&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">比如:git status 改成 git st,这样可以简化命令 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git config --global alias.st status +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="存储当前的修改但不用提交-commit">存储当前的修改,但不用提交 commit +</h2><p>详解可以参考<a class="link" href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137602359178794d966923e5c4134bc8bf98dfb03aea3000" target="_blank" rel="noopener" +>廖雪峰老师的 git 教程</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="保存当前状态包括-untracked-的文件">保存当前状态,包括 untracked 的文件 +</h2><p>untracked 文件:新建的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-stashes">展示所有 stashes +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash list +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-stash-的状态">回到某个 stash 的状态 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash apply &lt;stash@{n}&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到最后一个-stash-的状态并删除这个-stash">回到最后一个 stash 的状态,并删除这个 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash pop +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除所有的-stash">删除所有的 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash clear +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从-stash-中拿出某个文件的修改">从 stash 中拿出某个文件的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;stash@{n}&gt; -- &lt;file-path&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-tracked-的文件">展示所有 tracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files -t +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-untracked-的文件">展示所有 untracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有忽略的文件">展示所有忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others -i --exclude-standard +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的文件">强制删除 untracked 的文件 +</h2><p>可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,<strong>注意两点</strong>:</p> +<ol> +<li>clean 后,删除的文件无法找回</li> +<li>不会影响 tracked 的文件的改动,只会删除 untracked 的文件</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;file-name&gt; -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的目录">强制删除 untracked 的目录 +</h2><p>可以用来删除新建的目录,<strong>注意</strong>:这个命令也可以用来删除 untracked 的文件。详情见上一条</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;directory-name&gt; -df +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示简化的-commit-历史">展示简化的 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --pretty=oneline --graph --decorate --all +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把某一个分支导出成一个文件">把某一个分支导出成一个文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git bundle create &lt;file&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从包中导入分支">从包中导入分支 +</h2><p>新建一个分支,分支内容就是上面 git bundle create 命令导出的内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone repo.bundle &lt;repo-dir&gt; -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="执行-rebase-之前自动-stash">执行 rebase 之前自动 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rebase --autostash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程仓库根据-id拉下某一状态到本地分支">从远程仓库根据 ID,拉下某一状态,到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch origin pull/&lt;id&gt;/head:&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="详细展示一行中的修改">详细展示一行中的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --word-diff +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="清除-gitignore-文件中记录的文件">清除 gitignore 文件中记录的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean -X -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-alias-和-configs">展示所有 alias 和 configs +</h2><p><strong>注意:</strong> config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --local --list (当前目录) +</span></span><span class="line"><span class="cl">git config --global --list (全局) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示忽略的文件">展示忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git status --ignored +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="commit-历史中显示-branch1-有的但是-branch2-没有-commit">commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log Branch1 ^Branch2 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中显示-gpg-签名">在 commit log 中显示 GPG 签名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --show-signature +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除全局设置">删除全局设置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global --unset &lt;entry-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="新建并切换到新分支上同时这个分支没有任何-commit">新建并切换到新分支上,同时这个分支没有任何 commit +</h2><p>相当于保存修改,但是重写 commit 历史</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout --orphan &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示任意分支某一文件的内容">展示任意分支某一文件的内容 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git show &lt;branch-name&gt;:&lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-下来指定的单一分支">clone 下来指定的单一分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone -b &lt;branch-name&gt; --single-branch https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-最新一次提交">clone 最新一次提交 +</h2><p>只会 clone 最近一次提交,将减少 clone 时间</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --depth=1 https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略某个文件的改动">忽略某个文件的改动 +</h2><p>关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><p>恢复 track 指定文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --no-assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略文件的权限变化">忽略文件的权限变化 +</h2><p>不再将文件的权限变化视作改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config core.fileMode false +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以最后提交的顺序列出所有-git-分支">以最后提交的顺序列出所有 Git 分支 +</h2><p>最新的放在最上面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git for-each-ref --sort=-committerdate --format=&#39;%(refname:short)&#39; refs/heads/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中查找相关内容">在 commit log 中查找相关内容 +</h2><p>通过 grep 查找,given-text:所需要查找的字段</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --all --grep=&#39;&lt;given-text&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把暂存区的指定-file-放到工作区中">把暂存区的指定 file 放到工作区中 +</h2><p>不添加参数,默认是 -mixed</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制推送">强制推送 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push -f &lt;remote-name&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div>【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Fri, 29 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/cover.jpg" alt="Featured image of post 【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制" /><h4 id="一了解tortoisegit">一、了解TortoiseGit +</h4><p>TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。</p> +<p>由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。</p> +<p>TortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。</p> +<p>它是在<a class="link" href="https://www.gnu.org/licenses/gpl-2.0" target="_blank" rel="noopener" +>GPL</a>下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。</p> +<h4 id="二安装giit及tortoisegit">二、安装GIit及TortoiseGit +</h4><ul> +<li>Git下载官网: <a class="link" href="https://gitforwindows.org/index.html" target="_blank" rel="noopener" +>https://gitforwindows.org/index.html</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4a21fd0a6bd1453ba31032ce73c67d73.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>TortoiseGit下载官网:<a class="link" href="https://tortoisegit.org/download/" target="_blank" rel="noopener" +>https://tortoisegit.org/download/</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ba9793defe4baa02684e53320b79bde4.png" +loading="lazy" +alt="image-20220720090147944" +></p> +<ul> +<li>同时下载语言包</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b9cb668ce4c7a1ba2cda1a6bab5a0a76.png" +loading="lazy" +></p> +<p>当然这里也有百度网盘链接,也可点击下方链接进行下载</p> +<p>链接:<a class="link" href="https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs</a> +提取码:dzbs</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/db691a46832cc291932ff63fcc3e9a74.png" +loading="lazy" +alt="image-20220720090721507" +></p> +<h4 id="三tortoisegit配置">三、TortoiseGit配置 +</h4><p>完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67fb3421c49f0c5e90e76fa3c04c9b71.png" +loading="lazy" +alt="image-20220720091049882" +></p> +<p>这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/853a58d535b9e2370949ccb7917b80b5.png" +loading="lazy" +alt="image-20220720091218159" +></p> +<p>配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/e70b76490f6f5cfc699d79df3968e1fe.png" +loading="lazy" +alt="image-20220720091439829" +></p> +<p>点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[credential] +</span></span><span class="line"><span class="cl"> helper = store +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成后保存,关闭记事本,确定即可。</p> +<p>  则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。</p> +<p>  如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。</p> +<h4 id="四添加github-ssh-keys及密钥上传">四、添加GitHub SSH Keys及密钥上传 +</h4><p>首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\TortoiseGit\bin\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/33d7c521e31040d4921e11ab1b12bd74.png" +loading="lazy" +alt="image-20220720092721281" +> +<img src="https://img-blog.csdnimg.cn/img_convert/3f27c4682dc82b0bd0f3ef5c89a1df7e.png" +loading="lazy" +alt="image-20220720093308539" +></p> +<p>然后复制下方公钥,</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2a5f6daf15cc2e9935764b207b726cf7.png" +loading="lazy" +alt="image-20220720093236525" +></p> +<p>打开github,完成下图操作:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/52cf49261a89b3186083dfb7240ea8dd.png" +loading="lazy" +alt="image-20220815182247315" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/1db55857a0118c8cabc02f9a5c4bb19b.png" +loading="lazy" +alt="image-20220815182404425" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b406ac32656957356de898117c6bb17f.png" +loading="lazy" +alt="image-20220815182541297" +></p> +<h4 id="五使用tortoisegit提交代码到远端仓库">五、使用TortoiseGit提交代码到远端仓库 +</h4><p>在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/846315f99c2e767666f7be83437e4969.png" +loading="lazy" +alt="image-20220815185026555" +></p> +<p>鼠标右键可以看到选项<code>Git在这里创建版本库</code>,点击创建版本库</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bcb80e2391a690906240fd0d1b197e7a.png" +loading="lazy" +alt="image-20220815185825412" +></p> +<p>鼠标右键打开TortoiseGit-&gt;设置(Settings)-&gt;Git-&gt;远端(Remote),进行如下配置</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a1f9b059fb25b079395ad2588d51c0c5.png" +loading="lazy" +alt="image-20220815191405483" +></p> +<p>此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9c4fbf6ee5360e497644e6330255a278.png" +loading="lazy" +alt="image-20220815190637369" +></p> +<p>我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">正常的:绿色的对号 +</span></span><span class="line"><span class="cl">被修改过的:红色感叹号 +</span></span><span class="line"><span class="cl">新添加的:蓝色的加号 +</span></span><span class="line"><span class="cl">未受控的(无版本控制的):蓝色的问号 +</span></span><span class="line"><span class="cl">忽略不受控的:灰色的减号 +</span></span><span class="line"><span class="cl">删除的:红色的x号 +</span></span><span class="line"><span class="cl">有冲突的:黄色的感叹号 +</span></span></code></pre></td></tr></table> +</div> +</div><p>鼠标右键添加文件</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f146752e79d7bd6a4e9287e2c32ad3c1.png" +loading="lazy" +alt="image-20220815191829438" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/50b75011172011ae724d81bd921f8fdc.png" +loading="lazy" +alt="image-20220815191933736" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a9acdcdf6d14730de5e91df7564f65f8.png" +loading="lazy" +alt="image-20220815192002035" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/6439911282c3c25bde45fa033f3a58b3.png" +loading="lazy" +alt="image-20220815192321480" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/73d32ab54fc9914ea2d1a967c5b91065.png" +loading="lazy" +alt="image-20220815193032859" +></p> +<p><strong><code>注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次</code></strong></p> +<p>总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)</p> +<p><em><strong><code>添加-&gt;提交-&gt;拉取-&gt;推送</code></strong></em></p> +<p>那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!</p> \ No newline at end of file diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index_hu344c1fa4f15fd328833362988690574d_18346_120x120_fill_q75_box_smart1.jpg" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index_hu344c1fa4f15fd328833362988690574d_18346_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..5e78fa3f1 Binary files /dev/null and "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/index_hu344c1fa4f15fd328833362988690574d_18346_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/1/index.html" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/1/index.html" new file mode 100644 index 000000000..8b2529e8c --- /dev/null +++ "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/ + \ No newline at end of file diff --git "a/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/2/index.html" "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/2/index.html" new file mode 100644 index 000000000..23a63ed5e --- /dev/null +++ "b/categories/git\347\211\210\346\234\254\346\216\247\345\210\266/page/2/index.html" @@ -0,0 +1,56 @@ +Category: Git版本控制 - Pager 2 - kurisaW +

Categories

6 pages

Git版本控制

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。

\ No newline at end of file diff --git a/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b.jpg b/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b.jpg new file mode 100644 index 000000000..39fb96e6b Binary files /dev/null and b/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b.jpg differ diff --git a/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b_hu984c878b37337626c10b859073c5cf7d_1956545_250x150_fill_q75_box_smart1.jpg b/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b_hu984c878b37337626c10b859073c5cf7d_1956545_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..d83748779 Binary files /dev/null and b/categories/harmonyos/index.9f5c2411ff5d4b15c0aa7df6b95b479b_hu984c878b37337626c10b859073c5cf7d_1956545_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/harmonyos/index.html b/categories/harmonyos/index.html new file mode 100644 index 000000000..c16c987ab --- /dev/null +++ b/categories/harmonyos/index.html @@ -0,0 +1,55 @@ +Category: HarmonyOS - kurisaW +

Categories

1 page

HarmonyOS

鸿蒙(HarmonyOS,开发代号Ark,正式名称为华为终端鸿蒙智能设备操作系统软件)是华为自2012年开发的一款基于AOSP改良的操作系统。系统性能包括利用“分布式”技术将各款设备融合成一个“超级终端”,便于操作和共享各设备资源。系统架构支持多内核,包括Linux内核、LiteOS和鸿蒙微内核,可按各种智能设备选择所需内核,例如在低功耗设备上使用LiteOS内核。

\ No newline at end of file diff --git a/categories/harmonyos/index.jpg b/categories/harmonyos/index.jpg new file mode 100644 index 000000000..39fb96e6b Binary files /dev/null and b/categories/harmonyos/index.jpg differ diff --git a/categories/harmonyos/index.xml b/categories/harmonyos/index.xml new file mode 100644 index 000000000..0b4bd1c58 --- /dev/null +++ b/categories/harmonyos/index.xml @@ -0,0 +1,306 @@ +HarmonyOS on kurisaWhttps://kurisaw.github.io/categories/harmonyos/Recent content in HarmonyOS on kurisaWHugo -- gohugo.ioenFri, 07 Apr 2023 00:00:00 +0000【HarmonyOS】小熊派鸿蒙系统搭建https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建" /><h2 id="一bearpi-hm-micro-开发板介绍">一、BearPi-HM Micro 开发板介绍 +</h2><p>BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。</p> +<h2 id="二linux镜像下载">二、Linux镜像下载 +</h2><p>下载官方提供镜像(任选一种方式下载)</p> +<ul> +<li>Ubuntu20.04(大小8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1W0cgtXC5T2bv0lAya7eizA" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA</a> 提取码:1234</li> +<li>Ubuntu18.04(大小4.8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1YIdqlRWRGq_heAfrgQ7EPQ" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ</a> 提取码:1234</li> +</ul> +<h2 id="三bearpi-hm-micro编译环境配置">三、BearPi-HM Micro编译环境配置 +</h2><p>在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置</p> +<h4 id="1首先添加如下镜像源">1.首先添加如下镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /etc/apt/source.list +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 添加中科大源 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2更新镜像源">2.更新镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get update +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3安装依赖库及工具">3.安装依赖库及工具 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">gcc</span> <span class="n">g</span><span class="o">++</span> <span class="n">make</span> <span class="n">zlib</span><span class="o">*</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">e2fsprogs</span> <span class="n">pkg</span><span class="o">-</span><span class="n">config</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">perl</span> <span class="n">bc</span> <span class="n">openssl</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">libelf</span><span class="o">-</span><span class="n">dev</span> <span class="n">libc6</span><span class="o">-</span><span class="n">dev</span><span class="o">-</span><span class="n">amd64</span> <span class="n">binutils</span> <span class="n">binutils</span><span class="o">-</span><span class="n">dev</span> <span class="n">libdwarf</span><span class="o">-</span><span class="n">dev</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">tools</span> <span class="n">mtd</span><span class="o">-</span><span class="n">utils</span> <span class="n">gcc</span><span class="o">-</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabi</span> <span class="n">cpio</span> <span class="n">device</span><span class="o">-</span><span class="n">tree</span><span class="o">-</span><span class="n">compiler</span> <span class="n">net</span><span class="o">-</span><span class="n">tools</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> <span class="n">git</span> <span class="n">vim</span> <span class="n">openjdk</span><span class="o">-</span><span class="mi">11</span><span class="o">-</span><span class="n">jre</span><span class="o">-</span><span class="n">headless</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装hb">4.安装hb +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 安装hb命令 +</span></span><span class="line"><span class="cl">python3 -m pip install --user ohos-build==0.4.3 +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 环境变量配置</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 在.bashrc文件最后一行添加如下代码,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/.</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5测试hb是否安装成功">5.测试hb是否安装成功 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb -h +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071818214.png" +loading="lazy" +alt="image-20230407181805793" +></p> +<h2 id="四安装mkimage工具">四、安装mkimage工具 +</h2><p>首先解释这个工具的用途:<strong>用来制作不压缩或者压缩的多种可启动映象文件。</strong></p> +<h4 id="1新建tools目录">1.新建tools目录 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">~/</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2下载mkimagestm32工具到tools目录并复制到homebearpitools目录下">2.下载mkimage.stm32工具到<code>~/tools</code>目录,并复制到/home/bearpi/tools/目录下 +</h4><ul> +<li><a class="link" href="https://pan.baidu.com/share/init?surl=T2O8luJ0-8g5ZZYdOvWfqQ" target="_blank" rel="noopener" +>mkimage.stm32下载地址</a> 提取码:1234</li> +</ul> +<h4 id="3修改mkimagestm32文件权限">3.修改mkimage.stm32文件权限 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chmod</span> <span class="mi">777</span> <span class="o">~/</span><span class="n">tools</span><span class="o">/</span><span class="n">mkimage</span><span class="o">.</span><span class="n">stm32</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4设置环境变量">4.设置环境变量 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 将下面的代码拷贝至.bashrc文件最后,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/</span><span class="n">tools</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="五bearpi镜像导入vmware">五、bearpi镜像导入VMware +</h2><p>准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-&gt;打开(O),选择我们Linux镜像中的<code>BearPi-HM_Micro_Ubuntu.ovf</code>文件,等待镜像文件的导入,开始登录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">账户:bearpi +</span></span><span class="line"><span class="cl">密码:bearpi +</span></span></code></pre></td></tr></table> +</div> +</div><p>首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-&gt;设置-&gt;网络适配器-&gt;NAT模式</p> +<p>此时打开一个终端,输入ifconfig查看ip</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071852103.png" +loading="lazy" +alt="image-20230407185206621" +></p> +<h2 id="六源码获取">六、源码获取 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mkdir project &amp;&amp; cd project +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七编译代码">七、编译代码 +</h2><p>首先进入到项目文件夹中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi/project/bearpi-hm_micro_small/ +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行如下命令(普通用户模式终端下):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb set +</span></span></code></pre></td></tr></table> +</div> +</div><p>出现<code>[OHOS INFO] Input code path: </code>提示信息后再输入<code>.</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071902001.png" +loading="lazy" +alt="image-20230407190200859" +></p> +<p>我们选择<code>bearpi-hm_micro</code>后回车</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071904137.png" +loading="lazy" +alt="image-20230407190426957" +></p> +<p>输入下面的命令,等待下载程序完成</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb build -t notest --tee -f +</span></span></code></pre></td></tr></table> +</div> +</div><p>当出现<code>build success</code>时,即代表编译成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071916323.png" +loading="lazy" +alt="image-20230407191628183" +></p> +<h2 id="八查看编译出的固件位置">八、查看编译出的固件位置 +</h2><p>当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: <code>/home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro</code> 其中有以下文件是后面烧录系统需要使用的。</p> +<ul> +<li>OHOS_Image.stm32:系统镜像文件</li> +<li>rootfs_vfat.img:根文件系统</li> +<li>userfs_vfat.img:用户文件系统</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071919790.png" +loading="lazy" +alt="image-20230407191938678" +></p> +<p>我们将这三个文件复制到该目录下:<code>/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/</code>,方便后续烧录系统使用</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="n">OHOS_Image</span><span class="o">.</span><span class="n">stm32</span> <span class="n">rootfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="n">userfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">bearpi</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">bearpi</span><span class="o">-</span><span class="n">hm_micro_small</span><span class="o">/</span><span class="n">applications</span><span class="o">/</span><span class="n">BearPi</span><span class="o">/</span><span class="n">BearPi</span><span class="o">-</span><span class="n">HM_Micro</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">download_img</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071929824.png" +loading="lazy" +alt="image-20230407192926584" +></p> +<h2 id="九固件烧录">九、固件烧录 +</h2><h4 id="1准备工作">1.准备工作 +</h4><ul> +<li><a class="link" href="https://www.wch.cn/downloads/CH341SER_EXE.html" target="_blank" rel="noopener" +>CH340驱动</a></li> +<li><a class="link" href="https://www.st.com/en/development-tools/stm32cubeprog.html#get-software" target="_blank" rel="noopener" +>STM32CubeProgramme(v2.4.0+)</a></li> +</ul> +<h4 id="2连接开发板">2.连接开发板 +</h4><p>首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:<a class="link" href="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/" target="_blank" rel="noopener" +>【Linux系统开发】Ubuntu配置SFTP服务</a>)</p> +<p>当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。</p> +<p>我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111834424.png" +loading="lazy" +alt="image-20230411183456029" +></p> +<h4 id="3镜像烧录">3.镜像烧录 +</h4><ul> +<li> +<p>首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。</p> +</li> +<li> +<p>打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。</p> +</li> +<li> +<p>点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:<code>Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv</code>)。</p> +</li> +<li> +<p>点击Browse按钮,然后选择工程源码下的烧录镜像路径</p> +</li> +<li> +<p>点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111935608.png" +loading="lazy" +alt="image-20230411193521444" +></p> +<h4 id="4启动系统">4.启动系统 +</h4><p>将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111940183.jpg" +loading="lazy" +alt="3" +></p> \ No newline at end of file diff --git a/categories/harmonyos/index_hu984c878b37337626c10b859073c5cf7d_1956545_120x120_fill_q75_box_smart1.jpg b/categories/harmonyos/index_hu984c878b37337626c10b859073c5cf7d_1956545_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..db8c0e6a8 Binary files /dev/null and b/categories/harmonyos/index_hu984c878b37337626c10b859073c5cf7d_1956545_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/harmonyos/page/1/index.html b/categories/harmonyos/page/1/index.html new file mode 100644 index 000000000..d990ca206 --- /dev/null +++ b/categories/harmonyos/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/harmonyos/ + \ No newline at end of file diff --git a/categories/index.html b/categories/index.html new file mode 100644 index 000000000..58c27013f --- /dev/null +++ b/categories/index.html @@ -0,0 +1,57 @@ +Categories +

Section

15 pages

Categories

\ No newline at end of file diff --git a/categories/index.xml b/categories/index.xml new file mode 100644 index 000000000..8033cc4ce --- /dev/null +++ b/categories/index.xml @@ -0,0 +1 @@ +Categories on kurisaWhttps://kurisaw.github.io/categories/Recent content in Categories on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000RT-Threadhttps://kurisaw.github.io/categories/rt-thread/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/categories/rt-thread/<img src="https://kurisaw.github.io/categories/rt-thread/index.jpg" alt="Featured image of post RT-Thread" />experience_sharinghttps://kurisaw.github.io/categories/experience_sharing/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/categories/experience_sharing/<img src="https://kurisaw.github.io/categories/experience_sharing/index.jpg" alt="Featured image of post experience_sharing" />嵌入式素养提升https://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/<img src="https://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/index.jpg" alt="Featured image of post 嵌入式素养提升" />Micro_ROShttps://kurisaw.github.io/categories/micro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/categories/micro_ros/<img src="https://kurisaw.github.io/categories/micro_ros/index.jpg" alt="Featured image of post Micro_ROS" />Git版本控制https://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/<img src="https://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/index.jpg" alt="Featured image of post Git版本控制" />Linuxhttps://kurisaw.github.io/categories/linux/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/categories/linux/<img src="https://kurisaw.github.io/categories/linux/index.jpg" alt="Featured image of post Linux" />Matterhttps://kurisaw.github.io/categories/matter/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/categories/matter/<img src="https://kurisaw.github.io/categories/matter/index.jpg" alt="Featured image of post Matter" />NXP学习https://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/index.jpg" alt="Featured image of post NXP学习" />网络编程https://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/<img src="https://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/index.jpg" alt="Featured image of post 网络编程" />HarmonyOShttps://kurisaw.github.io/categories/harmonyos/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/categories/harmonyos/<img src="https://kurisaw.github.io/categories/harmonyos/index.jpg" alt="Featured image of post HarmonyOS" />资讯https://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/<img src="https://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/index.jpg" alt="Featured image of post 资讯" />数据结构与算法https://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/<img src="https://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/index.jpg" alt="Featured image of post 数据结构与算法" />operating_systemhttps://kurisaw.github.io/categories/operating_system/Thu, 10 Mar 2022 00:00:00 +0000https://kurisaw.github.io/categories/operating_system/<img src="https://kurisaw.github.io/categories/operating_system/index.jpg" alt="Featured image of post operating_system" />Cplusplushttps://kurisaw.github.io/categories/cplusplus/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/categories/cplusplus/<img src="https://kurisaw.github.io/categories/cplusplus/index.jpg" alt="Featured image of post Cplusplus" />C素养提升https://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/<img src="https://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/index.jpg" alt="Featured image of post C素养提升" /> \ No newline at end of file diff --git a/categories/linux/index.3277d684d91a88525c40c21e03a0370c.jpg b/categories/linux/index.3277d684d91a88525c40c21e03a0370c.jpg new file mode 100644 index 000000000..bfa0487a7 Binary files /dev/null and b/categories/linux/index.3277d684d91a88525c40c21e03a0370c.jpg differ diff --git a/categories/linux/index.3277d684d91a88525c40c21e03a0370c_hub76149109b397d43a9e03f7d3b35078f_20425_250x150_fill_q75_box_smart1.jpg b/categories/linux/index.3277d684d91a88525c40c21e03a0370c_hub76149109b397d43a9e03f7d3b35078f_20425_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..4d722af63 Binary files /dev/null and b/categories/linux/index.3277d684d91a88525c40c21e03a0370c_hub76149109b397d43a9e03f7d3b35078f_20425_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/linux/index.html b/categories/linux/index.html new file mode 100644 index 000000000..e7a158eaf --- /dev/null +++ b/categories/linux/index.html @@ -0,0 +1,57 @@ +Category: Linux - kurisaW +

Categories

13 pages

Linux

Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。Linux有上百种不同的发行版,如基于社区开发的debian、archlinux,和基于商业开发的Red Hat Enterprise Linux、SUSE、Oracle Linux等。

\ No newline at end of file diff --git a/categories/linux/index.jpg b/categories/linux/index.jpg new file mode 100644 index 000000000..bfa0487a7 Binary files /dev/null and b/categories/linux/index.jpg differ diff --git a/categories/linux/index.xml b/categories/linux/index.xml new file mode 100644 index 000000000..815c7a5dd --- /dev/null +++ b/categories/linux/index.xml @@ -0,0 +1,2985 @@ +Linux on kurisaWhttps://kurisaw.github.io/categories/linux/Recent content in Linux on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Linux系统开发】Linux常见开发汇总https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover.jpg" alt="Featured image of post 【Linux系统开发】Linux常见开发汇总" /><h2 id="1vmware-tools-灰色无法点击">1.vmware tools 灰色无法点击 +</h2><p>执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get update +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get upgrade +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install open-vm-tools-desktop -y +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2linux安装搜狗输入法">2.linux安装搜狗输入法 +</h2><p>终端安装 fcitx</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install fcitx +</span></span></code></pre></td></tr></table> +</div> +</div><p>到搜狗官方下载 deb 包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://shurufa.sogou.com/linux" target="_blank" rel="noopener" +>https://shurufa.sogou.com/linux</a></li> +</ul> +</blockquote> +<p>使用linux自带的安装程序安装输入法后,安装如下输入法依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 +</span></span><span class="line"><span class="cl">sudo apt install libgsettings-qt1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启即可</p> +<h2 id="3cmake安装指定版本">3.Cmake安装指定版本 +</h2><p>首先去官网下载所需版本的压缩包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://cmake.org/files/" target="_blank" rel="noopener" +>https://cmake.org/files/</a></li> +</ul> +</blockquote> +<p>执行解压命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -zxv -f cmake-3.22.6.tar.gz +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装相关依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install g++ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install make +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入解压后的cmake文件,执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./bootstrap +</span></span></code></pre></td></tr></table> +</div> +</div><p>编译构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">make +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo make install +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4ubuntu中使用-st-link">4.ubuntu中使用 st-link +</h2><p>安装依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc +</span></span></code></pre></td></tr></table> +</div> +</div><p>依次执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># download source code</span> +</span></span><span class="line"><span class="cl">git clone https://github.com/stlink-org/stlink +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> stlink +</span></span><span class="line"><span class="cl"><span class="c1"># build</span> +</span></span><span class="line"><span class="cl">cmake . +</span></span><span class="line"><span class="cl">make +</span></span><span class="line"><span class="cl"><span class="c1"># install</span> +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bin +</span></span><span class="line"><span class="cl">sudo cp st-* /usr/local/bin +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ../lib +</span></span><span class="line"><span class="cl">sudo cp *.so* /lib32 +</span></span><span class="line"><span class="cl"><span class="c1"># add rules</span> +</span></span><span class="line"><span class="cl">sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ +</span></span><span class="line"><span class="cl">sudo udevadm control --reload-rules +</span></span><span class="line"><span class="cl">sudo udevadm trigger +</span></span></code></pre></td></tr></table> +</div> +</div><p>尝试烧录代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#check if st-link is plugged</span> +</span></span><span class="line"><span class="cl">sudo st-info --probe +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># write hex</span> +</span></span><span class="line"><span class="cl">sudo st-flash --format ihex write myapp.hex +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 一般下载一次,会失败,需要刷入两次;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># write bin</span> +</span></span><span class="line"><span class="cl">sudo st-flash write in.bin 0x8000000 <span class="c1">#stm32f4xx</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># read bin</span> +</span></span><span class="line"><span class="cl">st-flash <span class="nb">read</span> out.bin 0x8000000 0x1000 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># restart</span> +</span></span><span class="line"><span class="cl"><span class="c1"># 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作</span> +</span></span><span class="line"><span class="cl">sudo st-flash reset +</span></span></code></pre></td></tr></table> +</div> +</div><p>具体的GDB调试可以参考这篇文章:</p> +<blockquote> +<ul> +<li><a class="link" href="https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html" target="_blank" rel="noopener" +>https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html</a></li> +</ul> +</blockquote>【Linux系统开发】Ubuntu配置SFTP服务https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover.jpg" alt="Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务" /><h2 id="sftp介绍">SFTP介绍 +</h2><p>SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)</p> +<h2 id="安装步骤">安装步骤 +</h2><h4 id="1目标">1.目标: +</h4><p>在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。</p> +<h4 id="2查看ubuntu系统信息">2.查看Ubuntu系统信息 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071010234.png" +loading="lazy" +alt="image-20230407101026858" +></p> +<h4 id="3检查是否已安装sftp">3.检查是否已安装SFTP +</h4><p>在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071011398.png" +loading="lazy" +alt="image-20230407101132327" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">client</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">client</span> +</span></span><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">server</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。</p> +<h4 id="4新建用户组sftp-users并新建用户sftp">4.新建用户组SFTP-users,并新建用户SFTP +</h4><p>为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">adduser</span> <span class="nf">sftp</span> <span class="p">(</span><span class="err">这部分会让你新建用户组信息,建议最好截图保存下</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5给sftp赋权并新建用户组ssh-users">5.给SFTP赋权并新建用户组SSH-users +</h4><p>将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">G</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="nb">false</span> <span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">a</span> <span class="o">-</span><span class="n">G</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">bbc2005</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6创建并设置sftp用户目录">6.创建并设置SFTP用户目录 +</h4><p>为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chown</span> <span class="nl">yifang</span><span class="p">:</span><span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chmod</span> <span class="mi">770</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="7修改ssh配置文件">7.修改SSH配置文件 +</h4><p>在sshd_config文件的最后添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssh</span><span class="o">/</span><span class="n">sshd_config</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">AllowGroups</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">Match</span> <span class="n">Group</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">ChrootDirectory</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">AllowTcpForwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"><span class="n">X11Forwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">ForceCommand</span> <span class="n">internal</span><span class="o">-</span><span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些内容的意思是:</p> +<ul> +<li>只允许ssh-users和SFTP-users通过SSH访问系统;</li> +<li>针对SFTP-users用户,增加一些额外的设置: +<ul> +<li>将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);</li> +<li>禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。</li> +<li>如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。</li> +</ul> +</li> +</ul> +<h4 id="8sftp客户端验证">8.SFTP客户端验证 +</h4><p>首先将虚拟机重启:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">reboot</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。</p> +<p>查看ubuntu网络ip地址</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ifconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071038531.png" +loading="lazy" +alt="image-20230407103802472" +>zhe</p> +<p>这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考<a class="link" href="https://blog.devyi.com/archives/418/" target="_blank" rel="noopener" +>RaiDrive—将网盘映射为磁盘</a>)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071044734.png" +loading="lazy" +alt="image-20230407104441660" +></p> +<p>此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071046125.png" +loading="lazy" +alt="image-20230407104643007" +></p>x210开发板根目录文件系统构建https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/Thu, 28 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/cover.jpg" alt="Featured image of post x210开发板根目录文件系统构建" /><h2 id="一开发板配置">一、开发板配置 +</h2><p>(使用secureCRT) +首先确保开发板完成以下配置:</p> +<p>主机IP: +<code>set ipaddr192.168.1.10</code> +服务器IP: +<code>set serverip 192.168.1.141</code> +网关: +<code>set gatewayip 192.168.1.1</code> +子网掩码: +<code>set netmask 255.255.255.0</code> +内核驱动设置: +<code>set bootcmd 'tftp 30008000 zImage; bootm 30008000'</code> +bootargs配置: +<code>set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200</code></p> +<p>最后输入save保存一下,这样开发板的网络和内核配置就设置好了</p> +<h2 id="二了解rootfs">二、了解rootfs +</h2><p>rootfs的两种表现形式: +1、nfs方式启动的文件夹形式的rootfs(主机)</p> +<p>2、用来烧录的镜像形式rootfs(开发板)</p> +<h2 id="三虚拟机文件配置">三、虚拟机文件配置 +</h2><h4 id="1目录配置">1.目录配置 +</h4><p>首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: +<code>rootfs x210_bsp</code></p> +<p>这时候我们需要知道这两个文件夹下有什么:</p> +<blockquote> +<ul> +<li>x210_bsp:用于uboot烧录和配置</li> +<li>rootfs:用于挂载开发板根文件系统</li> +</ul> +</blockquote> +<h4 id="2x210_bsp配置">2.x210_bsp配置 +</h4><p>首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压</p> +<p><img src="https://img-blog.csdnimg.cn/b4f56856fa1447b6b49ea43313bc141a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用</p> +<h4 id="3rootfs配置">3.rootfs配置 +</h4><p>首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压</p> +<p><img src="https://img-blog.csdnimg.cn/87600bf5cbf44ac3a94db3bc7bd01d78.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件</p> +<h4 id="4make-menuconfig">4.make menuconfig +</h4><p>进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单</p> +<blockquote> +<p>这里我们按下面操作完成网络配置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[*]Networking support ---&gt; +</span></span><span class="line"><span class="cl"> Networking options ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/a33a8e4e25bc4335b263cdbc59bd79a6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>网络文件系统设置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">File systems ---&gt; +</span></span><span class="line"><span class="cl"> [*]Networking File Systems ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>有需要把开发板作为服务器端的也可以选择把<code>NFS server support</code>设置打开,这里我们仅实验客户端</p> +<p><img src="https://img-blog.csdnimg.cn/ce11d76876fd463db53915dffde15776.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上配置结束后输入命令<code>make</code>编译,至此开发板uboot的网络和文件系统部分配置结束。</p> +<h2 id="四busybox的移植实战">四、busybox的移植实战 +</h2><h4 id="1了解busybox">1、了解busybox +</h4><blockquote> +<p>busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。</p> +</blockquote> +<h4 id="2busybox源码获取">2、busybox源码获取 +</h4><p><a class="link" href="http://www.busybox.net/" target="_blank" rel="noopener" +>busybox官网</a></p> +<p><code>注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)</code></p> +<h4 id="3busybox配置">3、busybox配置 +</h4><p>(1)修改Makefile</p> +<p>首先进入<code>~/rootfs/x210_rootfs/busybox-1.24.1</code>目录下</p> +<p>输入命令<code>vi Makefile</code>进入脚本进行以下修改</p> +<p>173行:<code>CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-</code> +<code>注意:此处的交叉编译链需要对照自己电脑的交叉编译链</code> +191行:<code>ARCH=arm</code></p> +<p><img src="https://img-blog.csdnimg.cn/988e15e86dde4807aa26011e6686bc6f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>(2)make menuconfig配置</p> +<p>Tip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 +因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。</p> +<p>make menuconfig</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Settings</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="n">Build</span> <span class="n">Options</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Build</span> <span class="n">BusyBox</span> <span class="n">as</span> <span class="n">a</span> <span class="k">static</span> <span class="n">binary</span><span class="p">(</span><span class="n">no</span> <span class="n">shared</span> <span class="n">libs</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Library</span> <span class="n">Tuning</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">vi</span><span class="o">-</span><span class="n">style</span> <span class="n">line</span> <span class="n">editing</span> <span class="n">commands</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Fancy</span> <span class="n">shell</span> <span class="n">prompts</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">Module</span> <span class="n">Utilities</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span> <span class="p">]</span><span class="n">Simplified</span> <span class="n">modutils</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">insmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">rmmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">lsmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">modprobe</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">depmod</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">System</span> <span class="n">Utilities</span><span class="o">---&gt;</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">mdev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">mdev</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">subdirs</span><span class="o">/</span><span class="n">symlinks</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">regular</span> <span class="n">expressions</span> <span class="n">substitutions</span> <span class="n">when</span> <span class="n">renaming</span> <span class="n">dev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">command</span> <span class="n">execution</span> <span class="n">at</span> <span class="n">device</span> <span class="n">addition</span><span class="o">/</span><span class="n">removal</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">loading</span> <span class="n">of</span> <span class="n">firmwares</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>大家学习使用的时候跟着上面的进行配置即可 +配置完成后,输入以下命令: +<code>make -j4</code> (4代表我主机的内核数) +无报错继续下一步: +make install</p> +<blockquote> +<p>解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装</p> +</blockquote> +<p>(3)设置busybox安装路径</p> +<ul> +<li><code>make menuconfig</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Busybox Settings ---&gt; +</span></span><span class="line"><span class="cl"> Installation Options (&#34;make install&#34; behavior) ---&gt; +</span></span><span class="line"><span class="cl"> (./)BusyBox installation prefix) //这里设置安装路径 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cf7de167425b47acaff070d610f78d1f.png" +loading="lazy" +></p> +<p>(4)解决方案 +在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。</p> +<p>make -j4编译可能遇到的问题:</p> +<ul> +<li><code>sync.c(text.sync_main+0x78):undefined reference to 'syncfs'</code></li> +</ul> +<p><code>分析:</code>可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。</p> +<p><code>解决方法:</code></p> +<p><code>make menuconfig</code> +点击/进入搜索,输入SYNC,根据提示禁用SYNC +最后再make -j4编译一下即可</p> +<p><img src="https://img-blog.csdnimg.cn/7defb1eda80748d29c73a564f2e631be.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2b4ded5286854f1ca4e7d8fae5e148c4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<img src="https://img-blog.csdnimg.cn/932a1580f3b54a5ca685be2b7c5c1dd7.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。</p> +<p>(5)make install简述</p> +<ul> +<li>默认安装位置:./_install</li> +<li>文件包含有:bin linuxrc sbin usr</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/002a97e1448542f784b04d188f6cb7f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->ls -l可以看到: linuxrc -&gt; bin/busybox //这个linuxrc其实就是个符号链接 <!-- raw HTML omitted --></p> +<p><img src="https://img-blog.csdnimg.cn/b97a1a96e2a94503832d05c0f8ca072e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->这里也不难发现,bin下的所有的符号链接都指向了busybox<!-- raw HTML omitted --></p> +<p>(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">make menuconfig +</span></span><span class="line"><span class="cl"> Busybox Settings —&gt; +</span></span><span class="line"><span class="cl"> Installation Options (“make install” behavior) —&gt; +</span></span><span class="line"><span class="cl"> (/root/rootfs/x210_rootfs)BusyBox installation prefix +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行<code>make install</code>后,回到被挂载的目录下,可以发现这四个文件已经生成。</p> +<h2 id="五nfs挂载根文件系统">五、NFS挂载根文件系统 +</h2><h4 id="1nfs简述">1.NFS简述 +</h4><ul> +<li>NFS 是Network File System的缩写,即网络文件系统。</li> +<li>功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。</li> +</ul> +<h4 id="2nfs服务器安装">2.NFS服务器安装 +</h4><p><code>sudo apt-get install nfs-kernel-server</code></p> +<h4 id="3nfs使用过程">3.NFS使用过程 +</h4><p>启动NFS服务器-&gt;启动NFS客户端-&gt;挂载NFS目录</p> +<h4 id="4nfs配置">4.NFS配置 +</h4><ul> +<li>输入命令<code>vim /etc/exports</code></li> +</ul> +<p>在最后一行修改</p> +<ul> +<li><code>&quot;文件挂载目录&quot; *(rw,sync,no_root_squash,no_subtree_check)</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a355d9b6e233404ea19531fa04947910.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>保存退出后,输入<code>mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs</code>(根据实际情况修改)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/9383c4e9c6e74c7485d07a6aec6f99fd.png" +loading="lazy" +></p> +<ul> +<li>输入命令<code>/etc/init.d/nfs-kernel-server restart</code>重启NFS服务</li> +</ul> +<h2 id="六开发板根目录配置">六、开发板根目录配置 +</h2><p>首先将etc目录放置到挂载根目录下</p> +<p>etc目录下载:</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>点击此处</a></p> +<h4 id="1inittab文件详解">1.inittab文件详解 +</h4><p>&lt;1&gt;添加一个典型的inittab文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>inittab下载</a></p> +<p>&lt;2&gt;inittab格式解析</p> +<p><code>id:runlevels:action:process</code></p> +<p><img src="https://img-blog.csdnimg.cn/4f374d2fe1ca4f7da6f22403e314525f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>解释:</p> +<ul> +<li>id:标识符,即代表记录的名字</li> +<li>runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/dd8867359c0c44c6945fc29dbf0a90a3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>action:用于描述该级别该执行什么操作(部分说明)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/99fb967e453c456b989bd57ec0e84020.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>process:具体执行的命令</li> +</ul> +<p>&lt;3&gt;了解busybox init与inittab之间的关系</p> +<ul> +<li>busybox init进程主要完成系统的初始化工作。</li> +</ul> +<p>busybox init进程的工作流程:</p> +<blockquote> +<p><!-- raw HTML omitted -->为init设置信号处理过程-&gt;初始化控制台-&gt;剖析/etc/inittab文件-&gt;执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS-&gt;执行所有导致 init 暂停的 inittab 命令(动作类型: wait)-&gt;执行所有仅执行一次的 inittab(动作类型: once)<!-- raw HTML omitted --></p> +</blockquote> +<ul> +<li>一旦完成以上工作, init 进程便会<code>循环执行</code>以下进程:</li> +</ul> +<blockquote> +<p>&lt;1&gt;执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) +&lt;2&gt;执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)</p> +</blockquote> +<ul> +<li>简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。</li> +</ul> +<p>注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。</p> +<p>&lt;4&gt;配置 +vi命令打开inittab模板文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#first:run the system script file 注释 +</span></span><span class="line"><span class="cl">::sysinit:/etc/init.d/rcS //在控制台初始化之前执行rcS +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::askfirst:-/bin/sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::ctrlaltdel:-/sbin/reboot //执行控制台时的打印信息 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#umount all filesystem //同时按住3键可以重启 +</span></span><span class="line"><span class="cl">::shutdown:/bin/umount -a -r//关机时接触挂载init +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#restart init process//重启时启动 +</span></span><span class="line"><span class="cl">::restart:/sbin/init +</span></span></code></pre></td></tr></table> +</div> +</div><p>修改脚本: +<img src="https://img-blog.csdnimg.cn/0ccb3db4d10c417b9eeb5526f87c7793.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rcs文件详解">2.rcS文件详解 +</h4><p>&lt;1&gt;添加一个典型的rcS文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>rcS下载</a></p> +<p>&lt;2&gt;rcS文件解析</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/sh 需要继续添加环境变量,在后面:/new 即可 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">PATH</span><span class="o">=</span>/sbin:/bin:/usr/sbin:/usr/bin +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">runlevel</span><span class="o">=</span>S +</span></span><span class="line"><span class="cl"><span class="nv">prevlevel</span><span class="o">=</span>N +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">umask</span> <span class="m">022</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> PATH runlevel prevlevel +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -a +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>PATH=xxx</li> +</ul> +<blockquote> +<p>PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。</p> +</blockquote> +<ul> +<li>runlevel=</li> +</ul> +<blockquote> +<p>linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/2c17661c32464ad8a0c96c654e622289.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>umask=</li> +</ul> +<blockquote> +<p>umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。</p> +</blockquote> +<ul> +<li>mount -a</li> +</ul> +<blockquote> +<p>mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)</p> +</blockquote> +<h4 id="3rcs实战">3.rcS实战 +</h4><p>首先将前面提供的etc压缩包模板下载至共享文件夹</p> +<p>&lt;1&gt;输入命令打开rcS脚本:<code>vi etc/init.d/rcS</code>。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了</p> +<p>&lt;2&gt;mdev</p> +<blockquote> +<p>udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。</p> +</blockquote> +<p>rcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在<code>rcS</code>文件中添加以下与mdev有关的2行配置项后:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echo /sbin/mdev &gt; /proc/sys/kernel/hotplug +</span></span><span class="line"><span class="cl">mdev -s +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/d84ea4a6677a4af08741ba6c4b6db580.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>再次启动系统后发现/dev目录下生成了很多的设备驱动文件</p> +<p>&lt;3&gt;hostname</p> +<p><code>我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名</code></p> +<p>hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。</p> +<ul> +<li>添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname</li> +</ul> +<p>&lt;4&gt;ifconfig</p> +<p>(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40</p> +<p><img src="https://img-blog.csdnimg.cn/5842d7cc0dd94c3fbd348189e908f09b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>&lt;5&gt;mount挂载测试</p> +<p>这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="k">var</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">tmp</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="o">......</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,<code>输入mkdir命令在根目录依次创建即可</code>。</p> +<h2 id="七动态链接库的拷贝">七、动态链接库的拷贝 +</h2><h4 id="1静态编译链接测试">1.静态编译链接测试 +</h4><p>首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a.c file-&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">int main() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> printf(&#34;hello world!\n&#34;); +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2解决办法">2.解决办法: +</h4><p><code>拷贝一份动态链接库文件到开发板根目录下</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3解释">3.解释: +</h4><p><img src="https://img-blog.csdnimg.cn/6e39e3914f954ff7967b904a8aa576c5.png" +loading="lazy" +></p> +<p>这时候执行命令./a.out发现可以正常打印</p> +<h4 id="4strip工具">4.strip工具 +</h4><p>动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在<code>传统的嵌入式系统中flash空间是有限的</code>,为了<code>节省空间</code>常常把这些符号信息去掉。这样节省空间并且不影响运行。</p> +<p>去掉符号信息的命令:</p> +<p><code>arm-linux-strip *so*</code></p> +<h2 id="八ext2格式镜像烧录">八、ext2格式镜像烧录 +</h2><h4 id="1确定文件夹格式的rootfs可用">1. 确定文件夹格式的rootfs可用 +</h4><p>前面我们已经提前配置好,此处不再赘述</p> +<p><img src="https://img-blog.csdnimg.cn/560f47331e76495994c412e7f9e97425.png" +loading="lazy" +></p> +<h4 id="2ext2镜像制作">2.ext2镜像制作 +</h4><ul> +<li> +<p>首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。</p> +</li> +<li> +<p>然后输入以下命令:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">losetup /dev/loop1 rootfs.ext2 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mke2fs -m 0 /dev/loop1 10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -t ext2 /dev/loop1 ./ext2_rootfs/ +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时我们复制一份开发板根目录到ext2_rootfs下</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp rootfs.ext2 /mnt/hgfs/Myshare/ -f +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>进入~/rootfs目录,执行清除卸载命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">umount /dev/loop1 +</span></span><span class="line"><span class="cl">losetup -d /dev/loop1 +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时在rootfs目录下可以看见生成了一个rootfs.ext2镜像文件,我们将其复制到共享文件夹下,然后再将其复制到电脑<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>fastboot</a>目录下,执行uboot烧录操作,借鉴该博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a></li> +</ul> +<p>至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!</p> +<hr> +<p>参考资料:</p> +<ul> +<li> +<p><a class="link" href="https://blog.csdn.net/wangweijundeqq/article/details/82533485?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>Linux开发之根文件系统构建及过程详解</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010299133/article/details/93414146" target="_blank" rel="noopener" +>busybox init进程和/etc/inittab关系</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010311609/article/details/123137181?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165080397516782184664736%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165080397516782184664736&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-123137181.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=NFS%E6%8C%82%E8%BD%BDlinux&#43;&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>NFS-LINUX挂载实践</a></p> +</li> +</ul>Ubuntu命令查看手册https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/Mon, 25 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/cover.jpg" alt="Featured image of post Ubuntu命令查看手册" /><h2 id="进程管理类">进程管理类 +</h2><p>1.top命令</p> +<blockquote> +<ul> +<li>top命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。</li> +<li>top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。</li> +</ul> +</blockquote> +<p>2.htop命令</p> +<blockquote> +<ul> +<li>htop命令是top的改进版。</li> +<li>默认情况下,大多数Linux发行版本都没有安装htop。</li> +<li>htop命令显示的信息与top相同,但它的界面更人性化。</li> +</ul> +</blockquote> +<p>3.pstree</p> +<blockquote> +<ul> +<li>pstree命令也可以显示进程信息。</li> +<li>它以树的形式显示进程。</li> +</ul> +</blockquote> +<p>4.kill</p> +<blockquote> +<ul> +<li>kill命令可以根据进程ID来杀死进程。</li> +<li>你可以使用ps -A,top,或者grep命令获取到进程ID。</li> +</ul> +</blockquote> +<pre><code>从技术层面来讲,kill命令可以发送任何信号给一个进程。 +你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。 +</code></pre> +<hr> +<h2 id="文件操作类基础篇">文件操作类(基础篇) +</h2><blockquote> +<p><strong>新建文件:touch</strong><br> +详细文档通过 man [command] 查看</p> +</blockquote> +<blockquote> +<p><strong>管理文件</strong></p> +</blockquote> +<ul> +<li>rm: 删除文件或目录(-r)</li> +<li>mkdir 新建目录</li> +<li>cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r)</li> +<li>mv 移动或重命名文件、目录</li> +</ul> +<blockquote> +<p><strong>压缩tzip文件</strong></p> +</blockquote> +<ul> +<li>zip FileName.zip DirName # 将DirName本身压缩</li> +<li>zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩</li> +</ul> +<blockquote> +<p><strong>解压zip文件</strong></p> +</blockquote> +<ul> +<li>unzip filename</li> +</ul> +<blockquote> +<p><strong>查找含<code>spark</code>的目录、文件</strong></p> +</blockquote> +<ul> +<li>find /home/jack -name &lsquo;<em>spark</em>&rsquo;</li> +</ul> +<blockquote> +<p><strong>更改密码</strong></p> +</blockquote> +<ul> +<li>passwd</li> +</ul> +<blockquote> +<p><strong>更改文件名或移动文件位置</strong></p> +</blockquote> +<ul> +<li>语句:mv oldFileName newFileName</li> +<li>示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt</li> +</ul> +<blockquote> +<p><strong>删除文件</strong></p> +</blockquote> +<ul> +<li>删除文件: rm test.txt</li> +<li>删除空文件夹: rmdir test</li> +<li>删除非空文件夹及其目录下的所有文件夹及文件:rm -r test</li> +<li>删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt)</li> +</ul> +<h2 id="防火墙状态">防火墙状态 +</h2><p>首先需要输入安装命令: +<code>apt install ufw</code></p> +<blockquote> +<p>查看防火墙当前状态 +<code>sudo ufw status</code></p> +</blockquote> +<blockquote> +<p>开启防火墙 +<code>sudo ufw enable</code></p> +</blockquote> +<blockquote> +<p>关闭防火墙 +<code>sudo ufw disable</code></p> +</blockquote> +<blockquote> +<p>查看防火墙版本 +<code>sudo ufw version</code></p> +</blockquote> +<blockquote> +<p>默认允许外部访问本机 +<code>sudo ufw default allow</code></p> +</blockquote> +<blockquote> +<p>默认拒绝外部访问主机 +<code>sudo ufw default deny</code></p> +</blockquote> +<blockquote> +<p>允许外部访问443端口 +<code>sudo ufw allow 443</code></p> +</blockquote> +<blockquote> +<p>拒绝外部访问443端口 +<code>sudo ufw deny 443</code></p> +</blockquote> +<blockquote> +<p>允许某个IP地址访问本机所有端口 +<code>sudo ufw allow from 192.168.0.1</code></p> +</blockquote> +<h2 id="网络设置">网络设置 +</h2><blockquote> +<p>重置网卡 +sudo /etc/init.d/networking restart</p> +</blockquote>Study210利用SD运行流水灯程序https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post Study210利用SD运行流水灯程序" /><h2 id="1安装ecilpse">1.安装ecilpse +</h2><h4 id="1确认自己的pc机开发环境开发板光盘中有如下四个eclipse包">(1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包: +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_32.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_32.7z +</span></span></code></pre></td></tr></table> +</div> +</div><p>选择自己需求对应的安装包下载解压即可(<a class="link" href="https://download.csdn.net/download/qq_56914146/85162554" target="_blank" rel="noopener" +>此处可点击下载</a>)</p> +<h4 id="2配置好eclipse的环境变量">(2)配置好eclipse的环境变量 +</h4><p>借鉴<a class="link" href="https://blog.csdn.net/m0_46165586/article/details/107296429?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165018384616781685349830%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165018384616781685349830&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107296429.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=eclipse%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>Eclipse环境变量配置-超详细</a></p> +<h2 id="2开始工程的创建">2.开始工程的创建 +</h2><h4 id="1首先双击eclipseexe文件进入初次进入需要选择一个存储位置作为工程存放处workplace">(1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace) +</h4><h4 id="2建一个流水灯工程">(2)建一个流水灯工程 +</h4><p>首先在Project Explorer的空白栏右键单击-&gt;New-&gt;C Project +<img src="https://img-blog.csdnimg.cn/0b37eba37269446faf5de58793963da2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +项目名称填写LED_test +<img src="https://img-blog.csdnimg.cn/0b7cce5b3fa341f98792a316a1937054.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +点击next,finish</p> +<p>找到我们的项目工程示例,将全部文件复制到剪贴板 +<img src="https://img-blog.csdnimg.cn/2bbe14f0a69a46fe8328ce92f1492421.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键选择paste,选择粘贴全部 +<img src="https://img-blog.csdnimg.cn/842db416ea2c4929ac655d29bc4bfb07.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +这是粘贴好的文件项目 +<img src="https://img-blog.csdnimg.cn/d1dae4dddaf346b1be377c674fefdd35.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键Build Project或直接CTRL+B编译 +<img src="https://img-blog.csdnimg.cn/9389ca0a332143fdbfb650e41fb84f2b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 +<img src="https://img-blog.csdnimg.cn/776361da8d1045c3a39af79804bf0320.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +进入该目录下,可以发现生成了led.bin映像文件 +<img src="https://img-blog.csdnimg.cn/e497619b0ab74765aaffd33dc55be299.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="3下载源码到sd卡">3.下载源码到SD卡 +</h2><p>打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 +<img src="https://img-blog.csdnimg.cn/07008c13a27e41bebc960a47747c2283.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="4实例演示">4.实例演示 +</h2><h4 id="1清除开发板中的bootloader">(1)清除开发板中的bootloader +</h4><p>由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a>)</p> +<h4 id="2通过sd卡运行裸机程序">(2)通过SD卡运行裸机程序 +</h4><p>将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 +<img src="https://img-blog.csdnimg.cn/ddcba636b89841629cc4eba87b6a90b2.gif" +loading="lazy" +alt="在这里插入图片描述" +></p>Study210开发板刷安卓系统https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/Sat, 23 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/cover.jpg" alt="Featured image of post Study210开发板刷安卓系统" /><h2 id="一破坏bootloader">一、破坏BootLoader +</h2><blockquote> +<p>1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/c79baf4eb1e949c88d6bb50c32862354.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)</p> +</blockquote> +<blockquote> +<p>3.输入root(password:123456)</p> +</blockquote> +<blockquote> +<p>4.然后输入<code>busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync</code></p> +</blockquote> +<blockquote> +<p>5.回车后显示</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">1+0 records in +</span></span><span class="line"><span class="cl">1+O records out +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 +此时重新启动开发板就无法启动了</p> +</blockquote> +<h2 id="二sd卡刷机烧录uboot到sd卡中">二、SD卡刷机(烧录uboot到SD卡中) +</h2><blockquote> +<p>1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/958a8cf2a0554edd8e2d53d021490d4e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->此处如果SD烧写不成功,可尝试用管理员身份运行。 +<code>插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.</code></p> +<blockquote> +<p>2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)</p> +</blockquote> +<h2 id="三fastboot-下载安装镜像">三、fastboot 下载安装镜像 +</h2><blockquote> +<p>1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。</p> +</blockquote> +<blockquote> +<p>2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/bc1cb6ad4904482baaad59e05da074bc.png" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wex7LBk8-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415202849623.png)\]" +></p> +<blockquote> +<p>3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android</p> +</blockquote> +<blockquote> +<p><code>fastboot目录下应该包含的文件</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/850cde9ff40e4109a2b46cd186f93418.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p><code> Android中应该包含的文件(由于这里我烧写的是安卓系统)</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d97c6282c3ba46aba3a44b34a72e99a4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3DezB8H-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203108592.png)\]" +></p> +<blockquote> +<p>4.进行内核和系统的烧写 ,具体代码如下:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/eb401fcf50ec4f228025341cfcb28fca.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Dhso3IG-1650028395334)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203639928.png)\]" +></p> +<blockquote> +<p>同时在SecureCRT下可以看到下载结果</p> +</blockquote> +<blockquote> +<p>5.最后在windows控制台下输入<code> fastboot reboot</code>命令重启系统即可。</p> +</blockquote> +<h2 id="四dnw-刷机用fastboot刷android-">四、dnw 刷机(用fastboot刷Android ) +</h2><ul> +<li>准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/763acfc49ae34659b891a95ccd3de444.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaxHZTvW-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415204109660.png)\]" +></p> +<p>注意:</p> +<p>(1)安装<code>SecBulk.sys Njsmodi 2416 dnw drive</code>的驱动程序在<code>\X210V3S_A\tools\USB驱动\dnw_driver</code>下,安装驱动需要禁用数字签名(可参考<a class="link" href="https://blog.csdn.net/m0_37182543/article/details/80541418?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165002148616780271549615%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=165002148616780271549615&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-80541418.142%5ev9%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=Windows%E7%A6%81%E7%94%A8%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>win10如何永久关闭数字签名</a>)</p> +<p>(2)在使用dnw过程中需要长按电源键,否则会断开连接。</p> +<p>刷机步骤:</p> +<blockquote> +<p>1.将拨码开关拨到USB启动位置。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/51ddaa8b66494111899de8774b695007.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rua1zZN3-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415205448252.png)\]" +></p> +<blockquote> +<p>2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/63fbc995f8ab4752945842db148ad6a5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/170c0ec22ea4421daa7952994fdd3b0d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/e08d1f32d26d4558b078f85db271eab4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>3.(<code>同上操作</code>)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin</p> +</blockquote> +<blockquote> +<p><code> 注意!!!</code>:下载的同时要看<code>SecureCRT界面</code>,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。</p> +</blockquote> +<blockquote> +<p>4.回到secureCRT</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入fdisk -c 0 (进行分区) +</span></span><span class="line"><span class="cl">输入fastboot (查看分区) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/7676539a597a42d38993936ee760236a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<code>最后再输入</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fastboot -w +</span></span></code></pre></td></tr></table> +</div> +</div><p>全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。</p> +<p><img src="https://img-blog.csdnimg.cn/2982435176bb485abd152c2ab508d2cc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p>此文章参考于<a class="link" href="https://blog.csdn.net/madao1234/article/details/101104872" target="_blank" rel="noopener" +>S5PV210 Study210开发板刷系统</a></p>ifconfig不显示ip地址https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/cover.jpg" alt="Featured image of post ifconfig不显示ip地址" /><h4 id="ubuntu终端下命令ifconfig的问题解决">ubuntu终端下命令ifconfig的问题解决 +</h4><blockquote> +<p>问题一. ifconfig之后只显示lo,没有看到eth0 +问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 +问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<h4 id="问题一ifconfig之后只显示lo没有看到eth0-">问题一:ifconfig之后只显示lo,没有看到eth0 ? +</h4><blockquote> +<p>1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 +ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback +这边的设置是本地回路。在后面加上</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">iface eth0 inet static +</span></span><span class="line"><span class="cl">address 192.168.1.230 //(ip地址) +</span></span><span class="line"><span class="cl">netmask 255.255.255.0 //(子网掩码) +</span></span><span class="line"><span class="cl">gateway 192.168.1.1 //(网关) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。</p> +</blockquote> +<blockquote> +<p>2.eth0被关了 +输入命令行:ifconfig eth0 up #开启eth0</p> +</blockquote> +<hr> +<h4 id="问题二ifconfig之后显示eth0但是没有显示inet地址广播掩码-">问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”? +</h4><blockquote> +<p>1.先用sudo dhclient eth0更新IP地址 +2.然后运行sudo ifconfig eth0 +3.reboot</p> +</blockquote> +<hr> +<h4 id="问题三重启后ping命令不能使用因为dns还没设置编辑etcresolvconf加上dns服务器地址">问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。 +</h4><blockquote> +<p>设置好后,如果直接ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<pre><code>nameserver 8.8.8.8 +nameserver 8.8.4.4 +</code></pre> +<blockquote> +<p>这两个是Google提供的免费DNS服务器的IP地址</p> +</blockquote>x210开发板 虚拟驱动创建流程https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/cover.jpg" alt="Featured image of post x210开发板 虚拟驱动创建流程" /><h2 id="内核编译常用命令">内核编译常用命令 +</h2><p>安装模块 +<code>lsmod module_test.ko</code> +创建设备文件 +<code>mknod /dev/test c 250 0</code> +查看设备状态 +<code>lsmod module_test.ko</code> +查看设备注册信息(分为字符设备和块设备) +<code>cat /proc/devices</code></p> +<h2 id="知识补充">知识补充: +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span><span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">j</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:这里如果没有指定i值,则打印出来的是随机值 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 如果定义一个静态变量而没有赋值,则打印默认为0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="虚拟驱动创建流程">虚拟驱动创建流程 +</h2><p>首先进入x210_bsp/kernel</p> +<p>make menuconfig</p> +<p><img src="https://img-blog.csdnimg.cn/783c09aa06cb4a83a4df08d76d31c447.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/dc736c9d0d2b4ceaaaffcd6f90a1a16a.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/1193fb6e02be4c52a1d5951b0236ff38.png" +loading="lazy" +></p> +<p>make -j4</p> +<p>cp arch/arm/boot/zImage /tftpboot/ -f</p> +<p>重启开发板查看开发板设备</p> +<p>ls /sys/devices/platform/</p> +<p><img src="https://img-blog.csdnimg.cn/f57e4a58658e4380967bbfa1c0813864.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2f3b1acd43e740e68774ecbe2824ea2f.png" +loading="lazy" +></p> +<p>cd sys/class/leds</p> +<p>led_test_4编写完成后</p> +<p>编译不报错即可</p> +<p>cd /root/x210_bsp/kernel/drivers/leds/</p> +<p>cp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./</p> +<p>vi Makefile-&gt;</p> +<p><code>obj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o</code></p> +<p><img src="https://img-blog.csdnimg.cn/b30ce84418064d24a4e01c96218834f2.png" +loading="lazy" +></p> +<p>vi Kconfig更改依赖(添加以下文件)</p> +<p><code>config LEDS_S5PV210 tristate &quot;LED Support for S5PV210&quot; help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.</code></p> +<p><img src="https://img-blog.csdnimg.cn/43715e94bbcb4e8ab850492c919afc33.png" +loading="lazy" +></p> +<p>进入到x210_bsp/kernel</p> +<p>执行make menuconfig</p> +<p>可以发现生成了新的配置(Device Drivers-&gt; LED_Support),使能这个</p> +<p><img src="https://img-blog.csdnimg.cn/31b19678d8204209b05d62de54afd1d9.png" +loading="lazy" +></p> +<p>执行make编译</p> +<p><code> cp arch/arm/boot/zImage /tftpboot/ -f</code></p> +<p>secureCRT:</p> +<p>cd sys/class/leds</p> +<p>进入LED1,执行</p> +<p>echo 1 &gt; brightness // 灯亮</p> +<p>echo 0 &gt; brightness //灯灭</p> +<hr> +<p>最后附上源代码:</p> +<p><code>leds-s5pv210.c</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/module.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/init.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/fs.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/uaccess.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio-bank.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/regs-gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/ioport.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/io.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/cdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/device.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/leds.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED1 S5PV210_GPJ0(3) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED2 S5PV210_GPJ0(4) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED3 S5PV210_GPJ0(5) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_OFF 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_ON 0 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led1_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led1_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led2_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led2_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led3_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led3_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">s5pv210_led_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 申请GPIO +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="nf">gpio_request</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="s">&#34;led1_gpj0.3&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;gpio_request failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_direction_output</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led1&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led1_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led2&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led2_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led3&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led3_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">s5pv210_led_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">module_init</span><span class="p">(</span><span class="n">s5pv210_led_init</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">module_exit</span><span class="p">(</span><span class="n">s5pv210_led_exit</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_LICENSE</span><span class="p">(</span><span class="s">&#34;GPL&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_AUTHOR</span><span class="p">(</span><span class="s">&#34;WYQ&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_DESCRIPTION</span><span class="p">(</span><span class="s">&#34;module_test&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>Makefile</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#KERN_VER = $(shell uname -r) +</span></span></span><span class="line"><span class="cl"><span class="cp">#KERN_DIR = /lib/modules/$(KERN_VER)/build +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">KERN_DIR</span> <span class="o">=</span> <span class="o">/</span><span class="n">root</span><span class="o">/</span><span class="n">x210_bsp</span><span class="o">/</span><span class="n">kernel</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">obj</span><span class="o">-</span><span class="n">m</span> <span class="o">+=</span> <span class="n">leds</span><span class="o">-</span><span class="n">s5pv210</span><span class="p">.</span><span class="n">o</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">all</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nl">PHONY</span><span class="p">:</span><span class="n">clean</span> +</span></span><span class="line"><span class="cl"><span class="nl">clean</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> <span class="n">clean</span> +</span></span></code></pre></td></tr></table> +</div> +</div>ubuntu彻底删除通过apt方式安装的程序https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post ubuntu彻底删除通过apt方式安装的程序" /><p>以删除apache2为例,其它程序也都是这么删&hellip;<br> +1.先通过apt删除程序和相关配置文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>2.自动删除不使用的软件包</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get autoremove +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.找出与apache2相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dpkg --get-selections|grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>没有就不显示,如果有就删除这些相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove xxx +</span></span></code></pre></td></tr></table> +</div> +</div><p>4.查看apache2是否还有进程存在</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ps -ef |grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果有就杀掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo kill -9 8888 //后面接pid号码,用空格隔开 +</span></span></code></pre></td></tr></table> +</div> +</div><p>5.全局查找和apache2相关的文件,需要一定时间,稍等</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo find / -name apache2* +</span></span></code></pre></td></tr></table> +</div> +</div><p>将找到的文件逐个删掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo rm -rf /usr/share/bash-completion/completions/apache2ctl +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就彻底删除掉apache2了</p>ubuntu安装交叉编译工具链https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/cover.jpg" alt="Featured image of post ubuntu安装交叉编译工具链" /><h1 id="ubuntu安装交叉编译工具链附避坑指南">ubuntu安装交叉编译工具链(附避坑指南) +</h1><blockquote> +<p>1.打开Ubuntu,在终端进入/usr/local/目录下</p> +</blockquote> +<pre><code>cd /usr/local/ +</code></pre> +<blockquote> +<p>2.在local/目录下创建一个名为arm的文件夹</p> +</blockquote> +<pre><code>mkdir arm +</code></pre> +<blockquote> +<p>3.在自己的共享文件夹下找到<a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a>,并复制到之前创建的arm目录下</p> +</blockquote> +<pre><code>cp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/ +</code></pre> +<blockquote> +<p>4.进入到arm目录下,解压该其中文件</p> +</blockquote> +<pre><code>cd /usr/local/arm +tar -jxvf arm-2009q3.tar.bz2 +</code></pre> +<blockquote> +<p>5.然后执行:</p> +</blockquote> +<pre><code>cd arm-2009q3/bin +./arm-none-linux-gnueabi-gcc -v +</code></pre> +<p><code>注意:</code><!-- raw HTML omitted -->这里如果输入<code>./arm-none-linux-gnueabi-gcc -v</code>终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持</p> +<pre><code>sudo apt-get install libc6:i386 +</code></pre> +<p><!-- raw HTML omitted -->安装好了之后重新输入<code>./arm-none-linux-gnueabi-gcc -v</code> +<img src="https://img-blog.csdnimg.cn/b0660902aed64a88a257ed92b892b8f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<!-- raw HTML omitted -->操作成功!</p> +<blockquote> +<p>6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 +打开配置文件</p> +</blockquote> +<pre><code>sudo vim /etc/profile +</code></pre> +<blockquote> +<p>7.在vi界面末尾处加入</p> +</blockquote> +<pre><code>export PATH=$PATH:/usr/local/arm/arm-2009q3/bin +</code></pre> +<blockquote> +<p>8.回到主目录,查看交叉编译工具是否可用</p> +</blockquote> +<pre><code>cd ~ +source /etc/profile +</code></pre> +<p><code>注</code> <!-- raw HTML omitted -->这里如果没有出现相关信息,切换root用户再次输入命令</p> +<p>使用 <code>echo $PATH</code>查看交叉编译链的安装路径是否加入了环境变量。 +使用<code>arm-linux-gnueabihf-gcc -v</code>测试交叉编译链是否好使</p> +<blockquote> +<p>9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:</p> +</blockquote> +<pre><code>chmod 777 mk-arm-linux-.sh +./mk-arm-linux-.sh +</code></pre> +<p><code>这里由于运行时报错,原因详见</code><a class="link" href="https://blog.csdn.net/LWJdear/article/details/79868551?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=bash:%20./mk-arm-linux-.sh:%20Perm&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-79868551.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>解决linux的-bash: ./xx.sh: Permission denied</a></p> +<blockquote> +<p>ls查看,可以发现符号链接出现,到此,交叉编译链配置成功!</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/6dc86a581621467d8639643cc154877a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p><code>附件</code>:</p> +<ul> +<li> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a></p> +</li> +<li> +<p><code>mk-arm-linux-.sh脚本文件</code></p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ar -s arm-linux-ar +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-as -s arm-linux-as +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++ -s arm-linux-c++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-g++ -s arm-linux-g++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1 +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ld -s arm-linux-ld +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-nm -s arm-linux-nm +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-size -s arm-linux-size +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strings -s arm-linux-strings +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strip -s arm-linux-strip +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<p><code>有问题欢迎评论留言致信:</code><a class="link" href="https://blog.csdn.net/qq_56914146?type=blog" target="_blank" rel="noopener" +>blogs</a></p>ubuntu桌面恢复(20.04)https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/<img src="https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/cover.jpg" alt="Featured image of post ubuntu桌面恢复(20.04)" /><h3 id="恢复ubuntu2004默认桌面管理器">恢复ubuntu20.04默认桌面管理器 +</h3><ul> +<li> +<ul> +<li> +<ul> +<li><a class="link" href="#GDM_KDM_LightDM_SDDM_5" >一、GDM, KDM, LightDM, SDDM的区别和安装配置</a></li> +<li> +<ul> +<li><a class="link" href="#1GDMgnome_8" >1、GDM,gnome系列的图形管理器</a></li> +<li><a class="link" href="#2KDMSDDMKDE_17" >2、KDM,SDDM是KDE系列的图形管理器</a></li> +<li><a class="link" href="#3LightDM_27" >3、LightDM</a></li> +</ul> +</li> +<li><a class="link" href="#_37" >二、配置和切换</a></li> +<li><a class="link" href="#ubuntu2004_62" >三、恢复ubuntu20.04默认桌面管理器</a></li> +<li> +<ul> +<li><a class="link" href="#1_65" >1、打开终端,用管理员口令下载相关资源</a></li> +<li><a class="link" href="#2gnomeshell_71" >2、安装gnome-shell</a></li> +<li><a class="link" href="#3ubuntugnomedesktop_80" >3、安装ubuntu-gnome-desktop</a></li> +<li><a class="link" href="#4unitytweaktoolgnometweaktool_85" >4、安装unity-tweak-tool和gnome-tweak-tool</a></li> +<li><a class="link" href="#5_94" >5、安装完成后重启</a></li> +</ul> +</li> +</ul> +</li> +</ul> +</li> +</ul> +<p>起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能<a class="link" href="https://blog.csdn.net/irober/article/details/112608610" target="_blank" rel="noopener" +>远程控制桌面</a>了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(<strong>gnome图形管理器</strong>)也变成了我不喜欢的风格(<strong>轻量级的LightDM</strong>)了,大家以后要慎重。<br> +注意:我是个半吊子,仅供参考。</p> +<h3 id="一gdm-kdm-lightdm-sddm的区别和安装配置">一、GDM, KDM, LightDM, SDDM的区别和安装配置 +</h3><p><a class="link" href="https://blog.csdn.net/u014466109/article/details/105572470" target="_blank" rel="noopener" +>GDM, KDM, LightDM, SDDM的区别和安装配置</a><br> +<strong>gdm3,kdm 和 lightdm</strong> 都是显示管理器。 它们提供图形化登录并处理用户身份验证。</p> +<h4 id="1gdmgnome系列的图形管理器">1、GDM,gnome系列的图形管理器 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2kdmsddm是kde系列的图形管理器">2、KDM,SDDM是KDE系列的图形管理器 +</h4><p>kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3lightdm">3、LightDM +</h4><p>LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="二配置和切换">二、配置和切换 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。</p> +<p>要检查当前正在使用的显示管理器,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cat</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">X11</span><span class="o">/</span><span class="n">default</span><span class="o">-</span><span class="n">display</span><span class="o">-</span><span class="n">manager</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。</p> +<h3 id="三恢复ubuntu2004默认桌面管理器">三、恢复ubuntu20.04默认桌面管理器 +</h3><p><a class="link" href="https://www.zhihu.com/tardis/sogou/art/27659651" target="_blank" rel="noopener" +>恢复ubuntu20.04默认桌面管理器</a><br> +目前Ubuntu的主流桌面<strong>GNOME</strong>, Ubntu的内置桌面是<strong>Untiy</strong></p> +<h4 id="1打开终端用管理员口令下载相关资源">1、打开终端,用管理员口令下载相关资源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">Ctrl</span><span class="o">+</span><span class="n">Alt</span><span class="o">+</span><span class="n">T</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开终端,用管理员口令下载相关资源</p> +<h4 id="2安装gnome-shell">2、安装gnome-shell +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">shell</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<p>管理员权限需要输入密码,但是系统不会显示你输入的密码<br> +输入完成后,直接回车即可</p> +<h4 id="3安装ubuntu-gnome-desktop">3、安装ubuntu-gnome-desktop +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">ubuntu</span><span class="o">-</span><span class="n">gnome</span><span class="o">-</span><span class="n">desktop</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装unity-tweak-tool和gnome-tweak-tool">4、安装unity-tweak-tool和gnome-tweak-tool +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">unity</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5安装完成后重启">5、安装完成后重启 +</h4><p>然后一切恢复如初,仿佛没发生过。</p>x11vnc安装与配置https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/<img src="https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/cover.jpg" alt="Featured image of post x11vnc安装与配置" /><h1 id="1-安装x11vnc">1. 安装x11vnc +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install x11vnc -y +</span></span></code></pre></td></tr></table> +</div> +</div><p>直接安装成功。</p> +<h1 id="2-设置vnc密码">2. 设置vnc密码 +</h1><p>密码存储在/etc/目录里面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo x11vnc -storepasswd /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><p>放在这个位置,需要设置文件读取权限<br> +否则会提示密码校验失败</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><h1 id="3创建vnc配置文件">3.创建vnc配置文件 +</h1><p>在/etc/init 下创建一个x11vnc.conf的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> <span class="nb">cd</span> /etc/init +</span></span><span class="line"><span class="cl"> sudo gedit x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>文件内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#description &#34;xiaoqiang vnc server&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#start on runlevel [2345]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#stop on runlevel [06]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#script</span> +</span></span><span class="line"><span class="cl"> <span class="nb">exec</span> /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport <span class="m">5900</span> -shared +</span></span><span class="line"><span class="cl"><span class="c1">#end script</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。</p> +<h1 id="4启动vnc服务">4.启动vnc服务 +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/12b8d37ebfbb4160a7d50196cf3bd2b7.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了</p> +<h1 id="5设置自启动">5.设置自启动 +</h1><p>我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。</p> +<h2 id="1首先编写一个脚本">(1)首先编写一个脚本 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gedit x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>添加以下内容<br> +第一行是要添加的解释器,后面是要执行的指令内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>防止误删,从home移动到/etc/init.d/文件夹中<br> +并添加权限</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mv x11vnc.sh /etc/init.d/ +</span></span><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2添加启动项">(2)添加启动项 +</h2><p>点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。<br> +<img src="https://img-blog.csdnimg.cn/b1f7234307b64d9ca6844704a100a243.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +点击右侧添加,添加自动启动项。<br> +<img src="https://img-blog.csdnimg.cn/fd2f7303980f4e7598e7f4ce6950ef20.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +添加内容如下;重要的是第二行,</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bash /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>用bash启动才能成功,保存之后重启,确实可以开机自启了。<br> +<img src="https://img-blog.csdnimg.cn/caa1005977844d8baffbba60e7d6ea93.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="6x11vnc配置安装虚拟显卡驱动">6.x11vnc配置(安装虚拟显卡驱动) +</h1><p>如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示</p> +<h2 id="1首先还是安装命令">(1)首先还是安装命令 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install xserver-xorg-video-dummy +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2接下来就是创建配置文件-etcx11xorgconf">(2)接下来就是创建配置文件 <code>/etc/X11/xorg.conf</code> +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Section &#34;Device&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> Driver &#34;dummy&#34; +</span></span><span class="line"><span class="cl"> VideoRam 64000 +</span></span><span class="line"><span class="cl"> Option &#34;IgnoreEDID&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl"> Option &#34;NoDDC&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> HorizSync 15.0-100.0 +</span></span><span class="line"><span class="cl"> VertRefresh 15.0-200.0 +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Monitor &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Device &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> DefaultDepth 24 +</span></span><span class="line"><span class="cl"> SubSection &#34;Display&#34; +</span></span><span class="line"><span class="cl"> Depth 24 +</span></span><span class="line"><span class="cl"> Modes &#34;1280x720&#34; +</span></span><span class="line"><span class="cl"> EndSubSection +</span></span><span class="line"><span class="cl">EndSection +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3再修改个文件加点配置">(3)再修改个文件加点配置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /boot/firmware/usercfg.txt +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">framebuffer_width=1280 +</span></span><span class="line"><span class="cl">framebuffer_height=720 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>如果想要恢复显示器的连接,可以先使用ssh访问终端并将<code>/etc/X11/xorg.conf</code>这个文件删除,再次重启即可</strong></p>多线程技术学习(基于Linux)https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post 多线程技术学习(基于Linux)" /><h2 id="1linux多线程概念">1.Linux多线程概念 +</h2><blockquote> +<p><strong>(1)线程:指运行中的程序的调度单位。</strong></p> +</blockquote> +<blockquote> +<p><strong>(2)多线程的优点:</strong></p> +</blockquote> +<ul> +<li>运行与一个线程中的多个线程,他们彼此之间使用<strong>相同的地址空间</strong>,<strong>共享大部分数据</strong>,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。</li> +<li>进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式</li> +<li>应用程序响应速度提高</li> +<li>使多CPU系统更加高效</li> +<li>改善程序结构</li> +</ul> +<blockquote> +<p><strong>(3)线程的生命周期</strong></p> +</blockquote> +<p>就绪-&gt;运行-&gt;阻塞-&gt;终止</p> +<hr> +<h2 id="2linux线程实现">2.linux线程实现 +</h2><blockquote> +<p><strong>(1)线程创建</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含 +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) +</code></pre> +</li> +<li> +<p>函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数 <br> +arg: start_rtn的参数</p> +</li> +</ul> +<blockquote> +<p><strong>(2)线程退出</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +void pthread_exit(void * rval_ptr)</li> +<li>功能:终止调用线程Rval_ptr:线程退出返回值的指针。</li> +</ul> +<blockquote> +<p><strong>(3)线程等待</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_join(pthread_t tid,void **rval_ptr) +</code></pre> +</li> +<li> +<p>功能:阻塞调用线程,直到指定的线程终止。</p> +</li> +<li> +<p>函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针</p> +</li> +</ul> +<blockquote> +<p><strong>(4)线程标识获取</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +pthread_t pthread_self(void)</li> +<li>功能:获取调用线程的 thread identifier</li> +</ul> +<blockquote> +<p><strong>(5)线程清除</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> void pthread_cleanup_push(void (*rtn)(void *),void *arg) +</code></pre> +</li> +<li> +<p>功能:将清除函数压入清除栈</p> +</li> +<li> +<p>函数说明: +Rtn:清除函数 +Arg:清除函数的参数</p> +</li> +</ul> +<hr> +<h2 id="3线程同步的方法">3.线程同步的方法 +</h2><p>进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:</p> +<blockquote> +<p>互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions</p> +</blockquote> +<hr> +<h2 id="4线程的互斥">4.线程的互斥 +</h2><p>线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。</p> +<blockquote> +<p><strong>(1)创建</strong></p> +</blockquote> +<p>在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:</p> +<ul> +<li>对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER</li> +<li>对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。</li> +</ul> +<blockquote> +<p>函数使用: +头文件: +#include &lt;pthread.h&gt;</p> +</blockquote> +<pre><code>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) +int pthread_mutex_destroy(pthread_mutex_t *mutex) +</code></pre> +<blockquote> +<p><strong>(2)加锁</strong></p> +</blockquote> +<p>对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。</p> +<blockquote> +<p>函数使用:</p> +</blockquote> +<pre><code>int pthread_mutex_lock(pthread_mutex_t *mutex) +int pthread_mutex_trylock(pthread_mutex_t *mutex) +</code></pre> +<p>返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。</p> +<blockquote> +<p><strong>(3)解锁</strong></p> +</blockquote> +<p>在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。</p> +<pre><code>int pthread_mutex_unlock(pthread_mutex_t *mutex) +</code></pre> +<hr> +<h2 id="5互斥pk信号量">5.互斥PK信号量 +</h2><blockquote> +<p>Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:</p> +<ol> +<li>mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放</li> +<li>初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。</li> +</ol> +</blockquote> +<hr> +<h2 id="6信号量操作代码演示">6.信号量操作(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;semaphore.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">sem_t sem; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sem_wait(&amp;sem); // 接收信号量 +</span></span><span class="line"><span class="cl"> /* +</span></span><span class="line"><span class="cl"> Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 +</span></span><span class="line"><span class="cl"> 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> //while(strncmp(buf,&#34;end&#34;,3) != 0) +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> sem_init(&amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(scanf(&#34;%s&#34;,buf)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> sem_post(&amp;sem); //增加(解锁)sem指向的信号量 +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="7互斥操作函数演示">7.互斥操作(函数演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">pthread_mutex_t mutex; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sleep(1); +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 互斥加锁 +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 解锁 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_mutex_init(&amp;mutex,NULL); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 对互斥对象加锁锁定 +</span></span><span class="line"><span class="cl"> scanf(&#34;%s&#34;,buf); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 输入后解锁 +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> pthread_mutex_destroy(&amp;mutex); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="8条件变量代码演示">8.条件变量(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1">#include&lt;stdio.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;string.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;pthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;stdlib.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">子线程处理</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_cond_t</span> <span class="n">cond</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">flag</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="o">*</span><span class="k">func</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">flag</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span><span class="o">//</span> <span class="err">互斥加锁</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span><span class="o">//</span> <span class="err">线程同步等待</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> <span class="o">//</span> <span class="err">解锁</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_exit</span><span class="p">(</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_t</span> <span class="n">th</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="err">初始化条件变量</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">,</span><span class="k">func</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_create</span><span class="p">()</span><span class="err">函数在调用进程中启动一个新线程</span><span class="p">,</span><span class="err">创建成功返回</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_create error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;please input string,end with Enter.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">scanf</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">发送信号</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="s2">&#34;end&#34;</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;process end</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char .</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;wait reclaim child thread.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">函数等待由</span><span class="n">thread指定的线程结束</span><span class="err">。如果该线程已经终止,则</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">立即返回。</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_join error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;reclaim child thread successfully.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">条件变量销毁</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git a/categories/linux/index_hub76149109b397d43a9e03f7d3b35078f_20425_120x120_fill_q75_box_smart1.jpg b/categories/linux/index_hub76149109b397d43a9e03f7d3b35078f_20425_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..84e84a603 Binary files /dev/null and b/categories/linux/index_hub76149109b397d43a9e03f7d3b35078f_20425_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/linux/page/1/index.html b/categories/linux/page/1/index.html new file mode 100644 index 000000000..5175abe66 --- /dev/null +++ b/categories/linux/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/linux/ + \ No newline at end of file diff --git a/categories/linux/page/2/index.html b/categories/linux/page/2/index.html new file mode 100644 index 000000000..276f4f138 --- /dev/null +++ b/categories/linux/page/2/index.html @@ -0,0 +1,57 @@ +Category: Linux - Pager 2 - kurisaW +

Categories

13 pages

Linux

Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。Linux有上百种不同的发行版,如基于社区开发的debian、archlinux,和基于商业开发的Red Hat Enterprise Linux、SUSE、Oracle Linux等。

\ No newline at end of file diff --git a/categories/linux/page/3/index.html b/categories/linux/page/3/index.html new file mode 100644 index 000000000..f17ed415d --- /dev/null +++ b/categories/linux/page/3/index.html @@ -0,0 +1,57 @@ +Category: Linux - Pager 3 - kurisaW +

Categories

13 pages

Linux

Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。Linux有上百种不同的发行版,如基于社区开发的debian、archlinux,和基于商业开发的Red Hat Enterprise Linux、SUSE、Oracle Linux等。

\ No newline at end of file diff --git a/categories/matter/index.3968d3a28b171db13a46a79112d62891.jpg b/categories/matter/index.3968d3a28b171db13a46a79112d62891.jpg new file mode 100644 index 000000000..e64b1919c Binary files /dev/null and b/categories/matter/index.3968d3a28b171db13a46a79112d62891.jpg differ diff --git a/categories/matter/index.3968d3a28b171db13a46a79112d62891_hue83b50b66d2879f78d068a069bf95e8c_68735_250x150_fill_q75_box_smart1.jpg b/categories/matter/index.3968d3a28b171db13a46a79112d62891_hue83b50b66d2879f78d068a069bf95e8c_68735_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..67fbc9ba3 Binary files /dev/null and b/categories/matter/index.3968d3a28b171db13a46a79112d62891_hue83b50b66d2879f78d068a069bf95e8c_68735_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/matter/index.html b/categories/matter/index.html new file mode 100644 index 000000000..9190dce22 --- /dev/null +++ b/categories/matter/index.html @@ -0,0 +1,56 @@ +Category: Matter - kurisaW +

Categories

8 pages

Matter

Matter 是一个统一的开源应用层连接标准,旨在使开发人员和设备制造商能够连接和构建可靠、安全的生态系统,并提高互联家庭设备之间的兼容性。

\ No newline at end of file diff --git a/categories/matter/index.jpg b/categories/matter/index.jpg new file mode 100644 index 000000000..e64b1919c Binary files /dev/null and b/categories/matter/index.jpg differ diff --git a/categories/matter/index.xml b/categories/matter/index.xml new file mode 100644 index 000000000..a9170b081 --- /dev/null +++ b/categories/matter/index.xml @@ -0,0 +1,3547 @@ +Matter on kurisaWhttps://kurisaw.github.io/categories/matter/Recent content in Matter on kurisaWHugo -- gohugo.ioenSun, 20 Aug 2023 00:00:00 +0000【Matter】CHIP设备层设计笔记https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/<img src="https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover.jpg" alt="Featured image of post 【Matter】CHIP设备层设计笔记" /><h1 id="chip设备层设计笔记">CHIP设备层设计笔记 +</h1><p>本文档包含与 CHIP 设备层 ( <code>src/platform</code>) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。</p> +<p>这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。</p> +<p>本文档包含以下部分:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Device-Layer-Adaptation-Patterns" target="_blank" rel="noopener" +>设备层适配模式</a></li> +</ul> +<hr> +<h3 id="设备层适配模式">设备层适配模式 +</h3><p>设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。</p> +<p>CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。</p> +<p>作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。</p> +<p>为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。</p> +<p>尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。</p> +<p>以下各节描述了用于实现这些目标的一些模式。</p> +<ol> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Interface-and-Implementation-Classes" target="_blank" rel="noopener" +>接口和实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Method-Forwarding" target="_blank" rel="noopener" +>方法转发</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Target-Platform-Selection" target="_blank" rel="noopener" +>目标平台选择</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Generic-Implementation-Classes" target="_blank" rel="noopener" +>通用实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Overriding-Generic-Behaviors" target="_blank" rel="noopener" +>覆盖通用行为</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Multiple-Inheritance-and-Subclassing-of-Generic-Implementations" target="_blank" rel="noopener" +>通用实现的多重继承和子类化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Static-Virtualization-of-Generic-Implementation-Behavior" target="_blank" rel="noopener" +>通用实现行为的静态虚拟化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#-ipp-files-and-explicit-template-instantiation" target="_blank" rel="noopener" +>.cpp 文件和显式模板实例化</a></li> +</ol> +<hr> +<h3 id="接口和实现类">接口和实现类 +</h3><p>CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。</p> +<p>外部可见的<em><strong>抽象接口类</strong></em>定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。</p> +<p>实现<em><strong>类</strong></em>提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。</p> +<p>设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。</p> +<p>抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀<code>Impl</code>。在所有情况下,实现类都需要从其接口类公开继承。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for a specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="方法转发">方法转发 +</h3><p>接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。<code>this</code>这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪的重复模板模式</a> ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,<code>ImplClass</code>使转发方法定义更加简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* forward method call... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>作为转发方法目标的实现类上的方法称为*<strong>实现方法*</strong>。每一种转发方法都必须有相应的实现方法。</p> +<p>前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。</p> +<p>实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Let the forwarding methods on ConfigurationManager call implementation +</span></span><span class="line"><span class="cl"> methods on this class. */ +</span></span><span class="line"><span class="cl"> friend ConfigurationManager; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">private: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR _Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding implementation method... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding static implementation method... */ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="目标平台选择">目标平台选择 +</h3><p>实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of ConfigurationManager.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#define CONFIGURATIONMANAGERIMPL_HEADER \ +</span></span><span class="line"><span class="cl"> &lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h&gt; +</span></span><span class="line"><span class="cl">#include CONFIGURATIONMANAGERIMPL_HEADER +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span></code></pre></td></tr></table> +</div> +</div><p>该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。</p> +<p>每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如<code>ESP32</code>)。所有此类文件都具有相同的文件名(例如<code>ConfigurationManagerImpl.h</code>),并且每个文件都包含类似名称的类的定义(<code>ConfigurationManagerImpl</code>)。</p> +<p>特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 <code>src/adaptations/device-layer/ESP32</code>)。与特定于平台的头目录一样,这些子目录以目标平台命名。</p> +<p>设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 <code>--device-layer=&lt;target-platform&gt;</code>。传递 &ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET ESP32 +</span></span><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET_ESP32 1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>&ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。</p> +<h3 id="通用实现类">通用实现类 +</h3><p>通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。</p> +<p>为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。</p> +<p>通用实现基类被实现为遵循 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪重复模板模式的</a>C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Implementation provided by +</span></span><span class="line"><span class="cl"> generic base class. */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); /* &lt;-- Invoked when GetDeviceId() called. */ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="覆盖通用行为">覆盖通用行为 +</h3><p>如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。</p> +<p>新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using GenericImpl = GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Call the generic implementation to get the device id. */ +</span></span><span class="line"><span class="cl"> uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Special case the situation where the device id is not known. */ +</span></span><span class="line"><span class="cl"> if (deviceId == kNodeIdNotSpecified) { +</span></span><span class="line"><span class="cl"> deviceId = PLATFORM_DEFAULT_DEVICE_ID; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return deviceId; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现的多重继承和子类化">通用实现的多重继承和子类化 +</h3><p>具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericWiFiConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;, /* &lt;-- WiFi features */ +</span></span><span class="line"><span class="cl"> public GenericThreadConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Thread features */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on all platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on FreeRTOS platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl_FreeRTOS +</span></span><span class="line"><span class="cl"> : public GenericPlatformManagerImpl&lt;ImplClass&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现行为的静态虚拟化">通用实现行为的静态虚拟化 +</h3><p>在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。</p> +<p>例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过<code>GetDeviceId()</code>从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。</p> +<p><code>this</code>遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数<code>Impl()</code>有助于使代码简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericConfigurationManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ConfigurationManagerImpl</span> <span class="n">final</span> +</span></span><span class="line"><span class="cl"> <span class="p">:</span> <span class="n">public</span> <span class="n">ConfigurationManager</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">public</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">friend</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">delegate</span> <span class="n">to</span> <span class="n">the</span> <span class="n">implementation</span> <span class="k">class</span> <span class="n">to</span> <span class="n">read</span> <span class="n">the</span> <span class="s1">&#39;device-id&#39;</span> <span class="n">config</span> <span class="n">value</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="err">“</span><span class="n">device</span><span class="o">-</span><span class="n">id</span><span class="err">”</span><span class="p">,</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">ConfigurationManagerImpl</span><span class="p">::</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">read</span> <span class="n">value</span> <span class="n">from</span> <span class="n">platform</span><span class="o">-</span><span class="n">specific</span> <span class="n">key</span><span class="o">-</span><span class="n">value</span> <span class="n">store</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。</p> +<p>同样,委托是通过转换<code>this</code>指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericPlatformManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">Delegate</span> <span class="n">work</span> <span class="n">to</span> <span class="n">method</span> <span class="n">that</span> <span class="n">can</span> <span class="n">be</span> <span class="n">overridden</span> <span class="n">by</span> <span class="n">implementation</span> <span class="k">class</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">provide</span> <span class="n">default</span> <span class="n">implementation</span> <span class="n">of</span> <span class="n">DispatchEventToApplication</span><span class="p">()</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="cpp-文件和显式模板实例化">.cpp 文件和显式模板实例化 +</h3><p>C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。</p> +<p>为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀<code>.cpp</code>。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.cpp */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">CHIP_ERROR GenericConfigurationManagerImpl&lt;ImplClass&gt;::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。<a class="link" href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation" target="_blank" rel="noopener" +>为了避免这种情况,设备层使用显式模板实例化</a>的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件<code>extern template class</code>在使用模板类之前都包含一个声明。这告诉编译器<em>不要</em>在该上下文中实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.h */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Instruct the compiler to instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span></span><span class="line"><span class="cl"><span class="c1">// class only when explicitly asked to do so. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">extern</span> <span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并<code>template class</code>使用定义来强制显式实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.cpp */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Fully instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; class. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。</p>【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)" /><h1 id="如何在linux平台下测试matter应用级通信虚拟设备">如何在Linux平台下测试Matter应用级通信(虚拟设备) +</h1><hr> +<h2 id="准备工作">准备工作 +</h2><h3 id="1-递归克隆matter仓库">1. 递归克隆Matter仓库 +</h3><p>执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果克隆过程中发生报错,请执行如下命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout v1.0 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2-matter依赖项安装">2. Matter依赖项安装 +</h3><p>Matter 构建依赖于以下软件包及环境库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果通过<code> build_examples.py</code> 和 <code>-with-ui</code> 变体进行构建,也要安装 SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-matter环境构建">3. Matter环境构建 +</h3><p>执行<code>scripts/activate.sh</code>脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190833624.png" +loading="lazy" +alt="image-20230619083303148" +></p> +<p>如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-安装zap">4. 安装zap +</h3><blockquote> +<p>注意:zap 包目前不可用<code>arm64</code>(比如在 Raspberry PI 上编译时)。</p> +</blockquote> +<ul> +<li>**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node -v +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果安装的话不出意外会出现版本号。</p> +<ul> +<li><strong>Step2:zap安装</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> connectedhomeip/scripts/tools/zap +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">python3 zap_download.py +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是安装日志:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip +</span></span><span class="line"><span class="cl">2023-06-19 13:29:20 root INFO Data downloaded, extracting ... +</span></span><span class="line"><span class="cl">2023-06-19 13:29:25 root INFO Done extracting. +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_INSTALL_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step3:配置zap环境变量</strong></li> +</ul> +<p>我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为<code>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly</code>,在此目录下有个 zap 脚本,我们这个位置一定要记住!!</p> +<p>设置<code>ZAP_DEVELOPMENT_PATH</code>环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step4:运行zap引导程序</strong></li> +</ul> +<p>执行如下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./run_zaptool.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>效果如下:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191346155.png" +loading="lazy" +alt="image-20230619134658521" +></p> +<ul> +<li><strong>Step4:为了方便我们后续使用zap,我们设置root终端下自启动:</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">vi ~/.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>.bashrc</code>文件最末添加如下代码,也就是配置zap环境变量</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出!</p> +<h2 id="应用程序构建">应用程序构建 +</h2><p>在官方文档中提供有两种构建方式:</p> +<ul> +<li>通过脚本构建</li> +<li>使用 Gn 和 Ninja 命令构建</li> +</ul> +<h3 id="1-通过脚本构建">1. 通过脚本构建 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build_script.sh EXAMPLE_DIR OUTPUT_DIR <span class="o">[</span>ARGUMENTS<span class="o">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>build_script.sh</code> 是脚本的文件名;</li> +<li><code>EXAMPLE_DIR</code> 是示例项目的目录路径;</li> +<li><code>OUTPUT_DIR</code> 是构建输出的目录路径;</li> +<li><code>[ARGUMENTS]</code> 是可选的其他参数,用于设置gn和ninja命令的选项。</li> +</ul> +<h4 id="11-构建示例">1.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ <span class="nv">chip_tests_zap_config</span><span class="o">=</span><span class="se">\&#34;</span>app1<span class="se">\&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190835972.png" +loading="lazy" +alt="image-20230619083551820" +></p> +<h4 id="12-运行构建">1.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./out/simulated/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190843752.png" +loading="lazy" +alt="image-20230619084309631" +></p> +<h3 id="2-通过-gn-和-ninja-构建应用程序">2. 通过 gn 和 ninja 构建应用程序 +</h3><h4 id="21-构建示例">2.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span><span class="line"><span class="cl">gn gen --check --root<span class="o">=</span>examples/placeholder/linux out/simulated --args<span class="o">=</span><span class="s2">&#34;chip_tests_zap_config=\&#34;app1\&#34;&#34;</span> +</span></span><span class="line"><span class="cl">ninja -C out/simulated +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22-运行构建">2.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./out/app1/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191510937.png" +loading="lazy" +alt="image-20230619151054483" +></p> +<h2 id="测试应用程序">测试应用程序 +</h2><p>在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191513515.png" +loading="lazy" +alt="image-20230619151353417" +></p> +<p>我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> out/debug +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./chip-tool onoff on 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff off 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> accepted-command-list 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> on-time 0x654321 <span class="m">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191530858.png" +loading="lazy" +alt="image-20230619153015727" +></p> +<p>具体更多的使用命令可参考:<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md" target="_blank" rel="noopener" +>Chip tool</a></p> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/simulated_device_linux.md" target="_blank" rel="noopener" +>simulated_device_linux</a></li> +<li><a class="link" href="https://github.com/project-chip/zap" target="_blank" rel="noopener" +>zap</a></li> +</ul>【Matter】Matter学习笔记1https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/<img src="https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover.jpg" alt="Featured image of post 【Matter】Matter学习笔记1" /><h1 id="matter学习笔记1">Matter学习笔记1 +</h1><hr> +<p>在了解Matter之前,可以选择先了解以下前提知识:</p> +<ul> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118389957" target="_blank" rel="noopener" +>matter网络基础之—Thread</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118553988" target="_blank" rel="noopener" +>matter网络基础之—Wi-Fi</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/119253287" target="_blank" rel="noopener" +>边界路由器,网关和Wi-Fi接入点</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/120067170" target="_blank" rel="noopener" +>Thread地址(IPv6 and RLOC16)</a></li> +</ul> +<blockquote> +<p>以上资料来自CSDN博主:<a class="link" href="https://blog.csdn.net/qq_42860989" target="_blank" rel="noopener" +>Eagle115</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。</p> +<p>Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个<strong>统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准</strong>。</p> +<p>Matter 作为一个<strong>应用级的协议</strong>,向下屏蔽了<strong>设备制造商的生态和系统,让各种智能家居设备之间能相互通信</strong>。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。</p> +<p>Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:</p> +<ul> +<li><strong>低功耗蓝牙技术</strong>:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。</li> +<li><strong>二维码进行配置</strong>:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。</li> +<li><strong>Wi-Fi 技术进行高速数据传输</strong>:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。</li> +<li><strong>Thread 协议进行低速数据传输</strong>:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。</li> +</ul> +<h2 id="matter协议架构">Matter协议架构 +</h2><h3 id="1matter-over-ipv6">1.Matter Over IPV6 +</h3><p>该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。</p> +<p>IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。</p> +<p>下面是IPV4 和 IPV6 的一些区别:</p> +<table> +<thead> +<tr> +<th style="text-align:center">区别</th> +<th style="text-align:center">IPV4</th> +<th style="text-align:center">IPV6</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">地址长度</td> +<td style="text-align:center">32 bits</td> +<td style="text-align:center">128 bits</td> +</tr> +<tr> +<td style="text-align:center">地址数量</td> +<td style="text-align:center">约<strong>4x10^9</strong></td> +<td style="text-align:center">约<strong>3.4×10^38</strong></td> +</tr> +<tr> +<td style="text-align:center">地址类型</td> +<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> +<td style="text-align:center">通过 DHCPv6 动态分配</td> +</tr> +<tr> +<td style="text-align:center">安全性</td> +<td style="text-align:center">IPsec(Internet协议安全标准) 为可选项</td> +<td style="text-align:center">IPsec 为默认选项</td> +</tr> +<tr> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +</tr> +</tbody> +</table> +<h3 id="2matter协议架构">2.Matter协议架构 +</h3><p>Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121952614.png" +loading="lazy" +></p> +<p>为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此<strong>天生具备IP连接能力</strong>,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;</p> +<p>Matter 还支持<strong>桥接</strong>等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行<strong>Bridge</strong>;</p> +<p>由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!</p> +<h3 id="3matter标准协议架构">3.Matter标准协议架构 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121138795.png" +loading="lazy" +></p> +<p><strong>Matter标准协议架构总体流程分析:</strong></p> +<p>首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议<a class="link" href="" >Message Reliability Protocol</a>);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。</p> +<p>后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!</p> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p>原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。</p> +<p>在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。</p> +<p>Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为<strong>Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层</strong>。而 <strong>6LoWPAN协议</strong> 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。</p> +<p>因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。</p> +<h3 id="mesh组网">Mesh组网 +</h3><p>在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。</p> +<p>目前最流行的全屋WiFi方案主要有两种:<strong>Mesh路由器组网</strong>和<strong>AC+AP</strong>两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。</p> +<p>无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,<strong>无线Mesh网络</strong>中的<strong>AP</strong>可以采用<strong>无线连接</strong>的方式进行互连,并且<strong>AP间可以建立多跳的无线链路</strong>。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +loading="lazy" +alt="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +></p> +<p>这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:</p> +<h3 id="1单一网络拓扑">1.单一网络拓扑 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121601076.png" +loading="lazy" +></p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121516744.png" +loading="lazy" +></p> +<p>在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是<strong>Thread/802.15.4网络</strong>、<strong>Wi-Fi网络</strong>或<strong>以太网网络</strong>。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,<strong>前提是所有段都在链路层桥接</strong>。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。</p> +<p>在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。</p> +<p>在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为<strong>Fabric</strong>。</p> +<blockquote> +<p>注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。</p> +</blockquote> +<h3 id="2星形网络拓扑">2.星形网络拓扑 +</h3><ul> +<li><strong>AP(Access Point)</strong>:WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。</li> +<li><strong>STA(Station)</strong>:STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。</li> +<li><strong>BR(Border Router)</strong>:指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。</li> +<li><strong>ED(End device)</strong>:指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +<li><strong>R(Router)</strong>:指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。</li> +<li><strong>SED(Sleepy End Device)</strong>:指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121605090.png" +loading="lazy" +></p> +<p>星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。<strong>外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。</strong></p> +<p>在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。</p> +<p>该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。</p> +<blockquote> +<p>注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。</p> +</blockquote> +<h2 id="设备数据模型date-model">设备数据模型(Date Model) +</h2><p>在 Matter 中的设备具有明确定义的<strong>数据模型</strong> (<strong>DM</strong>),这是对设备功能的分层建模。在此层次结构的顶层,有一个<strong>Device</strong>。</p> +<h3 id="1设备和端点nodeendpoint">1.设备和端点(Node、Endpoint) +</h3><p>所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。</p> +<p>一组节点包含了多组<strong>Endpoint(端点)</strong>。<strong>而每个端点都封装了一个功能集</strong>。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122042737.png" +loading="lazy" +></p> +<h3 id="2节点角色node-roles">2.节点角色(Node roles) +</h3><p>在Matter 中,每一个物理设备都被称之为<strong>Node</strong>,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!</p> +<p><strong>Node roles</strong>是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:</p> +<ul> +<li><strong>Commissioner :执行</strong><a class="link" href="https://developers.home.google.com/matter/primer/commissioning" target="_blank" rel="noopener" +>调试</a>的节点 。</li> +<li><strong>控制器</strong>:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>开/关灯开关</a>)具有控制器角色。</li> +<li><strong>Controlee</strong> : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>On/Off Light Switch</a>。开/关灯开关只能<em>是</em>控制器。它不能是受控人。</li> +<li><strong>OTA Provider</strong> : 可以提供 OTA 软件更新的节点。</li> +<li><strong>OTA 请求者</strong>:可以请求 OTA 软件更新的节点。</li> +</ul> +<h3 id="3集群cluster">3.集群(Cluster) +</h3><p>在一个<strong>Endpoint</strong>中,一个 Node 有一个或多个<strong>Clusters</strong>。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的<em>开/关</em>集群,或可调光端点上的<em>电平控制集群。</em></p> +<p>一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。</p> +<h4 id="31-属性attributes">3.1 属性(Attributes) +</h4><p>在最后一层,我们会找到<strong>Attributes</strong>,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122111729.png" +loading="lazy" +></p> +<h4 id="32-命令commands">3.2 命令(Commands) +</h4><p>除了 Attributes 之外,Clusters 还有<strong>Commands</strong>,也就是<strong>触发 Cluster 进行某种行为的指令</strong>。它们等同于Matter远程过程调用的 DM。命令类似于<em>动词</em>,例如<em>Door Lock</em>集群上的 <em>lock door</em>。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。</p> +<h4 id="33-事件events">3.3 事件(Events) +</h4><p>最后,Clusters 也可能有<strong>Events</strong>,它<strong>可以被认为是过去状态转换的记录</strong>。虽然属性代表<strong>当前状态</strong>,但事件是<strong>过去</strong>的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122122628.png" +loading="lazy" +></p> +<p><code>Endpoint 0</code>作为<code>Utility Clusters</code><strong>保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新</strong>。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。</p> +<h3 id="4-cluster分类">4. Cluster分类 +</h3><p>cluster可以定义为<strong>工具(Utility) Cluster</strong>或<strong>应用(Application) Cluster</strong>。</p> +<h4 id="41-工具utility-cluster">4.1 工具(Utility) Cluster +</h4><p>工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。</p> +<blockquote> +<p>作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。</p> +</blockquote> +<h4 id="42-应用application-cluster">4.2 应用(Application) Cluster +</h4><p>应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。</p> +<blockquote> +<p>应用cluster示例:</p> +<ul> +<li>On/Off cluster —— client向server发送命令</li> +<li>Temperature Measurement cluster —— server向client报告数据</li> +</ul> +</blockquote> +<p>应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。</p> +<blockquote> +<p>示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。</p> +</blockquote> +<h3 id="5-clients-and-servers">5. Clients and Servers +</h3><p>Clusters 可能是<strong>Client Cluster</strong>或<strong>Server Cluster</strong>。服务器是<strong>有状态的</strong>,保存属性、事件和命令;而客户端是 <strong>无状态的</strong>,其职责是启动与远程服务器集群的<strong>交互</strong>,从而执行:</p> +<ul> +<li><strong>读取</strong>和<strong>写入</strong>其远程属性。</li> +<li><strong>读取</strong>其远程事件。</li> +<li><strong>调用</strong>其远程命令。</li> +</ul> +<p>虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有<code>controller/peripheral</code> 或 <code>leader/follower</code>关系。相反,关系是水平的:任何 Cluster 都可以是<strong>Server</strong>或<strong>Client</strong>。因此,<strong>对于不同的集群和功能,节点可能既是服务器又是客户端。</strong></p> +<p>例如,我们可能有两个台灯:<strong>节点 A</strong>和<strong>节点 B</strong>。两个节点都实现了一个<em>开/关灯</em>设备类型。此设备类型包括控制其各自物理光输出的<em>开/关服务器集群。</em></p> +<p>但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现<em>开/关客户端</em>集群,以便它可以控制服务器集群。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122240843.png" +loading="lazy" +></p> +<p>在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。</p> +<p>在下一节中,我们将详细介绍客户端和服务器集群如何交互: <strong>Interaction Model(交互模型)</strong>。</p> +<h2 id="交互模型">交互模型 +</h2><h3 id="1概念">1.概念 +</h3><p>如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。<strong>交互模型</strong>(<strong>IM</strong>),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。</p> +<p><strong>节点通过以下方式相互交互:</strong></p> +<ul> +<li>读取和订阅属性和事件</li> +<li>写入属性</li> +<li>调用命令</li> +</ul> +<p>每当一个节点与另一个节点建立加密通信序列时,它们就构成了<strong>交互</strong>关系。<strong>Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成</strong>,可以理解为 Node 之间的 IM 级消息。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306140839728.png" +loading="lazy" +></p> +<p>Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。</p> +<h4 id="11-发起者initiators-和目标targets">1.1 发起者(Initiators )和目标(Targets) +</h4><p>在Matter中,节点的发起目标被称为<strong>发起者(Initiators )</strong>,而响应的节点则作为<strong>目标(Target)</strong>。一般来说,发起者是客户端集群,而目标是客户端集群。</p> +<h4 id="12-组groups">1.2 组(Groups) +</h4><p>在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。</p> +<p>为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。</p> +<h4 id="13-路径path">1.3 路径(Path) +</h4><p><strong>当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。</strong></p> +<blockquote> +<p>注:Path 也可以使用<strong>Groups</strong>或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。</p> +</blockquote> +<p>Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。</p> +<p>Matter Path 使用规范:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;path&gt; = &lt;node&gt; &lt;endpoint&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span><span class="line"><span class="cl">&lt;path&gt; = &lt;group ID&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。</p> +<h4 id="14-定时和非定时timed--untimed">1.4 定时和非定时(Timed &amp; Untimed) +</h4><p>有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。</p> +<h3 id="2-read-transactions">2. Read Transactions +</h3><p>与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。</p> +<h4 id="21-读取请求操作read-request-action">2.1 读取请求操作(Read Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>在此 Action 中,Initiator 会查询 Target 提供的以下请求:</p> +<ul> +<li><strong>属性请求</strong>:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。</li> +<li><strong>事件请求</strong>:目标请求事件的零个或多个路径列表。</li> +</ul> +<p>目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141108121.png" +loading="lazy" +></p> +<h4 id="22-报告请求数据report-data-action">2.2 报告请求数据(Report Data Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>在此 Action 中,Target 响应:</p> +<ul> +<li><strong>属性报告(Attribute Reports)</strong>:读取操作请求中请求的零个或多个报告属性的列表。</li> +<li><strong>事件报告(Event Reports)</strong>:零个或多个报告事件的列表。</li> +<li><strong>抑制响应(Suppress Response)</strong>:一个标志,用于确定是否应抑制对此操作的<strong>状态响应。</strong></li> +<li><strong>订阅 ID(Subscription ID)</strong>:如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。</li> +</ul> +<h4 id="23-状态响应动作status-response-action">2.3 状态响应动作(Status Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者 -&gt; 目标</strong></p> +</blockquote> +<p>一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。</p> +<p>一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。</p> +<p>状态响应操作仅包含一个<strong>状态字段</strong>,该字段将确认操作成功或显示失败代码。</p> +<h3 id="3-subscription-transaction">3. Subscription Transaction +</h3><h4 id="31-订阅请求操作subscribe-request-action">3.1 订阅请求操作(Subscribe Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。</p> +<p>订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。</p> +<p>订阅请求操作包含:</p> +<ul> +<li><strong>Min Interval Floor(最小间隔层)</strong>:报告之间的最小间隔。</li> +<li><strong>Max Interval Ceiling(最大区间上限)</strong>:报告之间的最大间隔。</li> +<li>Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。</li> +<li>Event Reports(事件报告):零个或多个报告事件的列表。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141332135.png" +loading="lazy" +></p> +<p>在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:<strong>Primed Published Data</strong>。</p> +<p>然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。</p> +<p>目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。</p> +<h4 id="32-订阅响应操作subscribe-response-action">3.2 订阅响应操作(Subscribe Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>这是订阅交易的最后一个操作,并结束了该过程。这包括:</p> +<ul> +<li><strong>Subscription ID(订阅 ID)</strong>:标识订阅的整数。</li> +<li><strong>Min Interval(最小间隔)</strong>:最终确定的报告之间的最小间隔。</li> +<li><strong>Max Interval(最大间隔)</strong>:<em>最终</em>确定<em>的</em>报告之间的最大间隔。</li> +</ul> +<h3 id="4-write-transactions">4. Write Transactions +</h3><h4 id="41-不定时写入事务untimed-write-transaction">4.1 不定时写入事务(Untimed Write Transaction) +</h4><h5 id="411-写请求操作write-request-action">4.1.1 写请求操作(Write Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>与读取请求操作类似,在此操作中,发起者为目标提供:</p> +<ul> +<li><strong>Write Requests(写入请求)</strong>:包含路径和数据的一个或多个元组的列表。</li> +<li><strong>Timed Request(定时请求)</strong>:一个标志,指示此操作是否是定时写入事务的一部分。</li> +<li><strong>Suppress Response(抑制响应)</strong>:指示是否应抑制响应状态操作的标志。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141423081.png" +loading="lazy" +></p> +<h5 id="412-写响应操作write-response-action">4.1.2 写响应操作(Write Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<h5 id="413-不定时写入限制untimed-write-restrictions">4.1.3 不定时写入限制(Untimed Write Restrictions) +</h5><p>写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。</p> +<h4 id="42-定时写入事务timed-write-transaction">4.2 定时写入事务(Timed Write Transaction) +</h4><p>在定时写入事务中比非定时写入事务多了几个步骤。</p> +<h5 id="421-定时请求操作timed-request-action">4.2.1 定时请求操作(Timed request action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。</p> +<h5 id="422-写请求操作write-request-action">4.2.2 写请求操作(Write Request Action) +</h5><p>与前面描述的 <strong>4.1.1 写请求操作</strong> 相同。</p> +<h5 id="423-写响应操作write-response-action">4.2.3 写响应操作(Write Response Action) +</h5><p>与前面描述的 <strong>4.1.2 写响应操作</strong> 相同。</p> +<h5 id="424-定时写入限制timed-write-restrictions">4.2.4 定时写入限制(Timed Write Restrictions) +</h5><p>定时请求动作、写请求动作和写响应动作是单播的。</p> +<h3 id="5调用事务">5.调用事务 +</h3><p><strong>调用事务</strong>用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。</p> +<p>与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 <strong>交互模型:1.4.定时和非定时</strong></p> +<h4 id="51-不定时调用事务">5.1 不定时调用事务 +</h4><h5 id="511-调用请求操作invoke-request-action">5.1.1 调用请求操作(Invoke Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:</p> +<ul> +<li><strong>Invoke Requests(调用请求):集群命令</strong>的路径(PATH)列表 ,以及命令的可选参数,名为 <strong>Command Fields</strong>。</li> +<li>Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。</li> +<li>Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。</li> +<li><strong>Interaction ID</strong>:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。</li> +</ul> +<h5 id="512-调用响应操作invoke-response-action">5.1.2 调用响应操作(Invoke Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:</p> +<ul> +<li><strong>Invoke Responses(调用响应)</strong>:发送的每个调用请求的命令响应或状态列表。</li> +<li>Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。</li> +</ul> +<h5 id="513-不定时调用限制">5.1.3 不定时调用限制 +</h5><p>Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。</p> +<h4 id="52-定时调用事务">5.2 定时调用事务 +</h4><p>与定时写入事务类似,定时调用事务也从定时请求操作开始。</p> +<h5 id="521-定时请求操作">5.2.1 定时请求操作 +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141539988.png" +loading="lazy" +></p> +<h5 id="522-调用请求操作invoke-request-action">5.2.2 调用请求操作(Invoke Request Action) +</h5><p>与前面描述的 <strong>5.1.1 调用请求操作</strong> 相同。</p> +<h5 id="523-调用响应操作invoke-response-action">5.2.3 调用响应操作(Invoke Response Action) +</h5><p>与前面描述的 <strong>5.1.2 调用响应操作</strong> 相同。</p> +<h5 id="524-定时调用限制timed-invoke-restrictions">5.2.4 定时调用限制(Timed Invoke Restrictions) +</h5><p>所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。</p> +<p>Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。</p> +<hr> +<h2 id="参考资料">参考资料 +</h2><ul> +<li><a class="link" href="https://developers.home.google.com/matter/primer/device-data-model#parts_list" target="_blank" rel="noopener" +>https://developers.home.google.com/matter/primer/device-data-model#parts_list</a></li> +<li><a class="link" href="https://www.bilibili.com/video/BV1NL411T7Kj/?spm_id_from=333.788&amp;vd_source=40334d7415493efea293dacb3c13f0b4" target="_blank" rel="noopener" +>Matter技术及关键特性介绍</a></li> +</ul>【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul>【Matter】Matter环境构建参考文档https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/Wed, 24 May 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/<img src="https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/cover.jpg" alt="Featured image of post 【Matter】Matter环境构建参考文档" /><h1 id="matter-环境构建参考文档">Matter 环境构建参考文档 +</h1><hr> +<p>Matter支持用<a class="link" href="https://gn.googlesource.com/gn/" target="_blank" rel="noopener" +>GN</a>配置构建,一个快速且可扩展的元构建系统,生成输入到<a class="link" href="https://ninja-build.org/" target="_blank" rel="noopener" +>ninja</a>。</p> +<h2 id="经过测试的操作系统">经过测试的操作系统 +</h2><p>该构建系统已经在以下操作系统上进行了测试:</p> +<ul> +<li>macOS 10.15</li> +<li>Debian 11 (64 bit required)</li> +<li>Ubuntu 22.04 LTS</li> +</ul> +<h2 id="构建系统的特点">构建系统的特点 +</h2><p>Matter构建系统有以下特点:</p> +<ul> +<li>速度非常快,占用空间小</li> +<li>跨平台处理: Linux, Darwin, Embedded Arm, 等等</li> +<li>多种工具链和跨工具链的依赖性</li> +<li>集成了自动测试框架: ninja check</li> +<li>自省:&ldquo;gn desc&rdquo;。</li> +<li>自动格式化: <code>gn格式</code>。</li> +</ul> +<h2 id="检查matter的代码">检查Matter的代码 +</h2><p>要检查Matter资源库,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="同步子模块">同步子模块 +</h2><p>如果你已经签出了Matter的代码,运行下面的命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="先决条件">先决条件 +</h2><p>在构建之前,你必须安装一些操作系统的特定依赖。</p> +<h3 id="1在linux上安装先决条件">1.在Linux上安装先决条件 +</h3><p>在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\ +</span></span><span class="line"><span class="cl"> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev +</span></span><span class="line"><span class="cl"> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="用户界面的构建">用户界面的构建 +</h4><p>如果通过<code>build_examples.py</code>和<code>with-ui</code>变体构建,也要安装SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在macos上安装先决条件">2.在macOS上安装先决条件 +</h3><p>在macOS上,从 Mac App Store上安装 Xcode 。</p> +<h4 id="用户界面的构建-1">用户界面的构建 +</h4><p>如果构建<code>-with-ui</code>变体,也要安装 SDL2 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">brew install sdl2 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3在raspberry-pi-4上安装先决条件">3.在Raspberry Pi 4上安装先决条件 +</h3><p>完成以下步骤:</p> +<ol> +<li>使用:在 micro SD 卡上<code>rpi-imager</code>安装适用于 arm64 架构的 Ubuntu <em>22.04</em> 64 位<em>服务器操作系统。</em></li> +<li>启动SD卡。</li> +<li>用默认的用户账户 &ldquo;ubuntu &ldquo;和密码 &ldquo;ubuntu &ldquo;登录。</li> +<li>继续执行 <a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>在 Linux 上安装先决条件</a>。</li> +<li>安装一些Raspberry Pi的特定依赖项:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install pi-Bluetooth avahi-utils +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="6"> +<li>安装完 &ldquo;pi-bluetooth &ldquo;后,重新启动你的Raspberry Pi。</li> +</ol> +<h4 id="配置wpa_supplicant以存储永久变化">配置wpa_supplicant以存储永久变化 +</h4><p>默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:</p> +<ol> +<li>编辑 <code>dbus-fi.w1.wpa_supplicant1.service</code> 文件以使用配置文件来代替,运行以下命令:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="2"> +<li>运行以下命令,将wpa_supplicant的启动参数改为提供的值:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="3"> +<li>通过运行以下命令添加<code>wpa-supplicant</code>配置文件:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="4"> +<li>在<code>wpa-supplicant</code>文件中添加以下内容:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl_interface=DIR=/run/wpa_supplicant +</span></span><span class="line"><span class="cl">update_config=1 +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="5"> +<li>重新启动你的Raspberry Pi。</li> +</ol> +<h2 id="安装zap工具">安装ZAP工具 +</h2><p><code>bootstrap.sh</code>将下载一个兼容的ZAP工具版本并将其设置在<code>$PATH</code>。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a> 页面下载。</p> +<h3 id="1linux-arm">1.Linux ARM +</h3><p>Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置<code>$ZAP_DEVELOPMENT_PATH</code>(见下面 <code>使用哪种ZAP</code>一节)。</p> +<p>文件<code>scripts/setup/zap.json</code>包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a>。要作为源代码签出代码,相应的标签应该存在于zap中<a class="link" href="https://github.com/project-chip/zap/tags" target="_blank" rel="noopener" +>repository tags</a> 列表中。</p> +<p>命令示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">RUN <span class="nb">set</span> -x <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> mkdir -p /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git clone https://github.com/project-chip/zap.git /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git checkout <span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm config <span class="nb">set</span> user <span class="m">0</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm ci +</span></span><span class="line"><span class="cl">ENV <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2使用哪种zap">2.使用哪种ZAP +</h3><p>ZAP工具脚本使用以下检测,按重要性排序:</p> +<ul> +<li> +<p><code>$ZAP_DEVELOPMENT_PATH</code>指向一个ZAP检出。</p> +</li> +<li> +<p>如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。</p> +</li> +<li> +<p><code>$ZAP_INSTALL_PATH</code>指向<code>zap-linux.zip</code>或`zap-m</p> +</li> +</ul> +<h2 id="为构建做准备">为构建做准备 +</h2><p>在运行任何其他构建命令之前,<code>scripts/activate.sh</code>的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。</p> +<p>运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1更新环境">1.更新环境 +</h3><p>如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>脚本 <code>scripts/bootstrap.sh</code>从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。</p> +<h2 id="为主机操作系统linux或macos进行构建">为主机操作系统(Linux或macOS)进行构建 +</h2><p>运行以下命令,为主机平台构建所有的源代码、库和测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些命令生成了一个适合调试的配置。要配置一个构建,请指定<code>is_debug=false</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/host --args=&#39;is_debug=false&#39; 。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**目录名称 &ldquo;out/host &ldquo;可以是任何目录,通常是在<code>out</code>目录下构建。这个例子使用 <code>host</code> 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过<code>gn args</code>重新配置。</p> +</blockquote> +<p>要运行所有测试,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host check +</span></span></code></pre></td></tr></table> +</div> +</div><p>要想只运行<code>src/inet/tests</code>中的测试,可以运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host src/inet/tests:test_run +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja: no work to do +</span></span></code></pre></td></tr></table> +</div> +</div><p>这意味着测试在之前的构建中通过了。</p> +</blockquote> +<h2 id="使用build_examplespy">使用<code>build_examples.py</code> +</h2><p>该脚本<code>./scripts/build/build_examples.py</code>提供了一个统一的编译构建接口,可以使用<code>gn</code>、<code>cmake</code>、<code>ninja</code>和其他必要的工具来编译各种平台。</p> +<p>使用 <code>./scripts/build/build_examples.py targets</code> 来查看支持的目标。</p> +<p>构建命令的例子:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 编译并在主机上运行所有测试: +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang) +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个esp32的例子 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个 nrf 示例 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1libfuzzer单元测试">1.<code>libfuzzer</code>单元测试 +</h3><p><code>libfuzzer</code>单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如<code>asan</code>应该被使用。</p> +<p>可执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build +</span></span></code></pre></td></tr></table> +</div> +</div><p>之后,测试应该被定位在<code>out/linux-x64-tests-lang-asan-libfuzzer/tests/</code>。</p> +<h4 id="ossfuzz的配置"><code>ossfuzz</code>的配置 +</h4><p><code>ossfuzz</code>配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如<code>$CFLAGS</code>、<code>$CXXFLAGS</code>和<code>$lib_fuzzing_engine</code>。</p> +<p>你可能需要<code>libfuzzer</code>+<code>asan</code>的构建来代替本地测试。</p> +<h2 id="构建自定义配置">构建自定义配置 +</h2><p>构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:</p> +<ul> +<li>将<code>--args</code>选项传递给<code>gn gen</code>。</li> +<li>在输出目录上运行<code>gn args</code>。</li> +<li>编辑输出目录下的<code>args.gn</code>。</li> +</ul> +<p>要配置一个新的构建或编辑现有构建的参数,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn args out/custom +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><p>两个关键的内置构建参数是 <code>target_os</code> 和 <code>target_cpu</code>,它们分别控制构建的操作系统和CPU。</p> +<p>要查看所有可用的构建参数的帮助,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/custom +</span></span><span class="line"><span class="cl">gn args --list out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="构建实例">构建实例 +</h2><p>你可以通过两种方式构建例子。</p> +<h3 id="1将例子作为独立的项目来构建">1.将例子作为独立的项目来构建 +</h3><p>要把例子作为单独的项目来构建,在Matter的<code>third_party directory</code>,运行下面的命令,输入正确的路径到例子的正确路径(这里是 &ldquo;chip-shell&rdquo;):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd examples/shell +</span></span><span class="line"><span class="cl">gn gen out/debug +</span></span><span class="line"><span class="cl">ninja -C out/debug +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在顶层建立实例">2.在顶层建立实例 +</h3><p>你可以在Matter项目的顶层构建例子。请看下面的<code>统一构建</code>一节了解详情。</p> +<h2 id="统一构建">统一构建 +</h2><p>要构建一个近似于连续构建集的统一配置,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34;&#39; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/unified all +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。</p> +<p>这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/unified host_gcc +</span></span><span class="line"><span class="cl">ninja -C out/unified check_host_gcc +</span></span></code></pre></td></tr></table> +</div> +</div><p>用配置的名称替换<code>host_gcc</code>,它可以在根目录下的 &ldquo;BUILD.gn &ldquo;中找到。</p> +<p>你也可以用参数对生成的配置进行微调。比如说</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34; enable_host_clang_build=false&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><p>完整的列表请参见根目录<code>BUILD.gn</code>。</p> +<p>在统一的构建中,目标有多个实例,需要通过添加通过添加<code>(toolchain)</code>后缀来区分。使用<code>gn ls out/debug</code>来列出所有的目标实例。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">desc</span> <span class="n">out</span><span class="o">/</span><span class="n">unified</span> <span class="s1">&#39;//src/controller(//build/toolchain/host:linux_x64_clang)&#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 +必须作为构建参数提供。例如,要添加 <code>Simplelink cc13x2_26x2</code> 例子到统一构建中,安装<a class="link" href="https://www.ti.com/tool/SYSCONFIG" target="_blank" rel="noopener" +>SysConfig</a> 并添加以下构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#34;target_os=\&#34;all\&#34; enable_ti_simplelink_builds=true &gt; ti_sysconfig_root=\&#34;/path/to/sysconfig\&#34;&#34; +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<h2 id="获得帮助">获得帮助 +</h2><p>GN集成了帮助,你可以通过<code>gn help</code>命令访问。</p> +<p>请确保查看以下推荐的主题:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn帮助执行</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="err">语法</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="n">toolchain</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可参见 <a class="link" href="https://gn.googlesource.com/gn/&#43;/master/docs/quick_start.md" target="_blank" rel="noopener" +>快速入门指南</a>。</p> +<h2 id="自省">自省 +</h2><p>GN有各种自省工具来帮助你检查构建配置。下面的例子以<code>out/host</code>输出目录为例:</p> +<ul> +<li> +<p>显示一个输出目录中的所有目标:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn ls out/host +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示所有将被构建的文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn output out/host &#39;*&#39; +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示配置的目标的GN表示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/inet --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>将整个构建的GN表示转为JSON格式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host/ &#39;*&#39; --all --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示依赖关系树:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //:all deps --tree --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>查找依赖性路径:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn path out/host //src/transport/tests:test //src/system +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>列出与`libCHIP&rsquo;连接的有用信息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/lib include_dirs +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib defines +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib outputs +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 一切都是JSON格式 +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h2 id="覆盖范围">覆盖范围 +</h2><p>代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。</p> +<p>运行以下命令来启动该脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build_coverage.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> -c, --code 指定收集覆盖数据的范围。 +</span></span><span class="line"><span class="cl"> core&#34;:从Matter SDK的核心堆栈中收集覆盖数据。--default +</span></span><span class="line"><span class="cl"> clusters&#34;:从Matter SDK中的cluster实现中收集覆盖数据。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;:收集Matter SDK的覆盖数据。 +</span></span><span class="line"><span class="cl"> -t, --tests 指定哪些工具来运行覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;unit&#39;: 运行单元测试来驱动覆盖率检查。--default +</span></span><span class="line"><span class="cl"> &#39;yaml&#39;: 运行yaml测试来驱动覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;: 运行单元和yaml测试来驱动覆盖率检查。 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): <a class="link" href="https://matter-build-automation.ue.r.appspot.com/" target="_blank" rel="noopener" +>matter coverage</a>。</p> +<h2 id="维护事项">维护事项 +</h2><p>如果你对GN构建系统做了任何改变,下一次构建会自动重新生成<code>ninja</code>文件。不需要做任何事情。</p>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/Sat, 06 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/<img src="https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover.jpg" alt="Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)" /><h1 id="esp-matter环境下的应用实践">esp-matter环境下的应用实践 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><p>请确保你本地已经配置好 <code>esp-idf</code> 及<code>esp-matter</code>环境,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130484975?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter开发环境搭建</a></p> +<h2 id="设置环境变量">设置环境变量 +</h2><h3 id="1esp-idf">1.ESP-IDF +</h3><p>根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041609281.png" +loading="lazy" +alt="image-20230504160909004" +></p> +<h3 id="2esp-matter">2.ESP-Matter +</h3><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>Linux</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>macOS</a></li> +</ul> +<p>由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>此处</a></p> +<p>在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>准备编译matter所需环境。注:如切换了其他分支需要重新运行</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060133538.png" +loading="lazy" +alt="image-20230506013329415" +></p> +<p>激活编译matter环境</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041611578.png" +loading="lazy" +alt="image-20230504161123505" +></p> +<h2 id="matter-example编译下载">Matter Example编译下载 +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2选择esp设备">2.选择esp设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>初次执行这个命令发生了如下报错:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">AttributeError</span><span class="p">:</span> <span class="err">&#39;</span><span class="n">HTTPResponse</span><span class="err">&#39;</span> <span class="n">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="err">&#39;</span><span class="n">strict</span><span class="err">&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在GitHub上参考此<a class="link" href="https://github.com/espressif/esp-idf/issues/11340" target="_blank" rel="noopener" +>issue</a>,并执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时重新执行esp-matter安装脚本:</p> +<p>由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此<a class="link" href="https://github.com/kurisaW/Summer-of-Open-Source/issues/7" target="_blank" rel="noopener" +>issue</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="p">.</span><span class="n">environment</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后回到示例工程下继续执行esp设备选择</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时发生了新的错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060221146.png" +loading="lazy" +alt="image-20230506022134054" +></p> +<p>由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">rm</span> <span class="o">-</span><span class="n">r</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span><span class="o">/</span><span class="n">build</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后成功解决问题:</p> +<p><img src="https://user-images.githubusercontent.com/98592772/236539480-35af78e1-382f-4092-a25b-fb2a09004d0a.png" +loading="lazy" +alt="b372338ad9384db034000d7839549b5" +></p> +<h3 id="3编译工程">3.编译工程 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060250998.png" +loading="lazy" +alt="image-20230506025001282" +></p> +<h3 id="4sdk烧写">4.SDK烧写 +</h3><p>第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">erase_flash</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060252819.png" +loading="lazy" +alt="image-20230506025047817" +></p> +<p>烧录程序并打开串口监视</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>可以看到烧录进度:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060251334.png" +loading="lazy" +alt="image-20230506025133178" +></p> +<p>包括串口监视器的提示信息,同时执行以下命令可退出串口监视:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">CTRL</span> <span class="o">+</span> <span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060254172.png" +loading="lazy" +alt="image-20230506025401001" +></p> +<p>那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。</p> +<hr> +<p>参考链接:</p> +<p><a class="link" href="https://blog.csdn.net/hydfxy2018/article/details/122041168?spm=1001.2101.3001.6650.11&amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;utm_relevant_index=12" target="_blank" rel="noopener" +>Matter Over Wifi 例程体验(CHIP Over Wifi)</a></p> +<p><a class="link" href="https://blog.csdn.net/weixin_40209493/article/details/125814311?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168324979316800211536064%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=168324979316800211536064&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-125814311-null-null.142%5ev86%5econtrol_2,239%5ev2%5einsert_chatgpt&amp;utm_term=matter%E6%8A%A5%E9%94%99&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>ESP-Matter 环境测试</a></p> +<p><a class="link" href="https://blog.csdn.net/puweiqi/article/details/129474079?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;utm_relevant_index=3" target="_blank" rel="noopener" +>matter搭建环境</a></p> +<p><a class="link" href="https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html" target="_blank" rel="noopener" +>https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html</a></p>【Matter】esp-matter开发环境搭建https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【Matter】esp-matter开发环境搭建" /><h1 id="esp-matter开发环境搭建">esp-matter开发环境搭建 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><h3 id="1ubuntu2204磁盘容量不小于80g">1.Ubuntu22.04(磁盘容量不小于80G) +</h3><h3 id="2科学上网环境">2.科学上网环境 +</h3><p>由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。</p> +<p>参考链接:<a class="link" href="https://kurisaw.github.io/p/%e7%bb%8f%e9%aa%8c%e5%88%86%e4%ba%ablinux-%e7%8e%af%e5%a2%83%e4%b8%8bv2ray%e7%9a%84%e4%bd%bf%e7%94%a8/" target="_blank" rel="noopener" +>【经验分享】Linux 环境下v2ray的使用</a></p> +<h2 id="esp-idf-开发环境搭建">esp-idf 开发环境搭建 +</h2><h3 id="1esp-idf-依赖环境安装">1.ESP-IDF 依赖环境安装 +</h3><blockquote> +<p>参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:</p> +<ul> +<li>Problem1:执行 git submodule 速度慢</li> +<li>Problem2:执行install.sh 速度慢</li> +</ul> +<p>所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。</p> +<h3 id="2problem1-solution">2.Problem1 solution +</h3><p>首先使用递归克隆命令克隆整个仓库到文件夹下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-idf.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span> <span class="o">--</span><span class="n">recursive</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:</p> +<ul> +<li>jihu-mirror 使用(推荐)</li> +<li>submodule-update 使用(不推荐)</li> +</ul> +<h4 id="21--jihu-mirror-使用推荐">2.1 jihu-mirror 使用(推荐) +</h4><ul> +<li>Step 1:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-gitee-tools.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Step 2:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 使用如下命令将仓库的 URL 进行替换: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">url</span><span class="p">.</span><span class="nl">https</span><span class="p">:</span><span class="c1">//jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>当我们使用命令 <code>git clone https://github.com/espressif/esp-idf</code> 时,默认的 URL <code>https://github.com/espressif/esp-idf</code> 将被自动替换成 <code>https://jihulab.com/esp-mirror/espressif/esp-idf</code>。</p> +<ul> +<li>Step 3:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 启用镜像URL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">set</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用命令 <code>./jihu-mirror.sh unset</code> 恢复,不使用镜像的 URL。</p> +<ul> +<li>Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recursive https://github.com/espressif/esp-idf.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然如果不想使用镜像的URL可以使用如下命令进行恢复:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">unset</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22--submodule-update-使用不推荐">2.2 submodule-update 使用(不推荐) +</h4><ul> +<li> +<p>Step 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">gitee</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">EspressifSystems</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">.</span><span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>Step 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 仅克隆 esp-idf,不包含子模块 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-idf.git +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<ul> +<li>Step 3:</li> +</ul> +<p>可以有两种方式来更新 submodules。</p> +<ul> +<li> +<p>方式一</p> +<p>进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">EGT_PATH</span><span class="o">=$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入 esp-idf 目录执行 submodule-update.sh 脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd esp-idf +</span></span><span class="line"><span class="cl">$EGT_PATH/submodule-update.sh +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>方式二</p> +<p><code>submodule-update.sh</code> 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:<code>submodule-update.sh PATH_OF_PROJ</code>。</p> +<p>假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="o">./</span><span class="n">submodule</span><span class="o">-</span><span class="n">update</span><span class="o">.</span><span class="n">sh</span> <span class="o">~/</span><span class="n">git</span><span class="o">/</span><span class="n">esp32</span><span class="o">-</span><span class="n">sdk</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果要更新其他工程,可以同样方式。</p> +</li> +</ul> +<blockquote> +<p>值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!</p> +</blockquote> +<h3 id="3problem2-solution">3.Problem2 solution +</h3><p>下面说第二个问题:执行./install.sh速度慢的问题</p> +<p>在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 <code>IDF_GITHUB_ASSETS</code> 的环境变量来指定这个地址。在设置了 <code>IDF_GITHUB_ASSETS</code> 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">export</span> <span class="n">IDF_GITHUB_ASSETS</span><span class="o">=</span><span class="s">&#34;dl.espressif.com/github_assets&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后再执行安装命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这还报了一个错误</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041247286.png" +loading="lazy" +alt="image-20230504124717772" +></p> +<p>我们根据提示安装<code>python3.10-venv</code>,并再次执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="mf">.10</span><span class="o">-</span><span class="n">venv</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041249721.png" +loading="lazy" +alt="image-20230504124913620" +></p> +<p>至此,esp-idf 的安装工具就告一段落了。</p> +<h2 id="esp-matter开发环境搭建-1">esp-matter开发环境搭建 +</h2><blockquote> +<p>参考:<a class="link" href="https://github.com/espressif/esp-matter" target="_blank" rel="noopener" +>【乐鑫 Matter SDK GitHub】</a></p> +</blockquote> +<p>**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:<code>./jihu-mirror.sh unset</code>取消esp镜像!! **</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-matter.git +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git submodule update --init --recursive +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错&hellip;</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): started +</span></span><span class="line"><span class="cl"> error: subprocess-exited-with-error +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> × python setup.py bdist_wheel did not run successfully. +</span></span><span class="line"><span class="cl"> │ exit code: 1 +</span></span><span class="line"><span class="cl"> ╰─&gt; See above for output. +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> note: This error originates from a subprocess, and is likely not a problem with pip. +</span></span><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): finished with status &#39;error&#39; +</span></span><span class="line"><span class="cl"> ERROR: Failed building wheel for pycryptodome +</span></span><span class="line"><span class="cl"> Running setup.py clean for pycryptodome +</span></span><span class="line"><span class="cl"> Building wheel for gevent (pyproject.toml): started +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ...... +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们查看<code>install.sh</code>文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">basedir</span><span class="o">=</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">ESP_MATTER_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="nb">pwd</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">MATTER_PATH</span><span class="o">=</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">export</span> ESP_MATTER_PATH +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Running Matter Setup&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/scripts/bootstrap.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Run the zap_download.py and extract the path of installed binary</span> +</span></span><span class="line"><span class="cl"><span class="c1"># eg output before cut: &#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># output after cut: zap/zap-v2023.03.06-nightly</span> +</span></span><span class="line"><span class="cl"><span class="c1"># TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged</span> +</span></span><span class="line"><span class="cl"><span class="nv">zap_path</span><span class="o">=</span><span class="sb">`</span>python3 <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --sdk-root <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --extract-root .zap 2&gt;/dev/null <span class="p">|</span> cut -d<span class="o">=</span> -f2<span class="sb">`</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Check whether the download is successful.</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="nv">$zap_path</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Failed to install zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"> deactivate +</span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span><span class="s2">/.zap&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> rm -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl">mkdir <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl">mv <span class="nv">$zap_path</span>/* <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/ +</span></span><span class="line"><span class="cl">rm -r <span class="nv">$zap_path</span> +</span></span><span class="line"><span class="cl">chmod +x <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/zap-cli +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Building host tools&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">gn --root<span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">&#34;</span> gen <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl">ninja -C <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Host tools built at: </span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">/out/host&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Exit Matter environment&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">deactivate +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for mfg_tool&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/tools/mfg_tool/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for Matter&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;All done! You can now run:&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34; . </span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">/export.sh&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install build-essential python3-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pkg-config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" +loading="lazy" +alt="image-20230504145216015" +></a></p> +<p>接着在安装<code>zap-cli</code>的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./install.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" +loading="lazy" +alt="image-20230504150238105" +></a></p> +<p>最后看到<code>All done!</code>即代表环境安装成功!</p> +<p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" +loading="lazy" +alt="image-20230504153243388" +></a></p> +<p>至此,esp-matter开发环境搭建成功!</p> \ No newline at end of file diff --git a/categories/matter/index_hue83b50b66d2879f78d068a069bf95e8c_68735_120x120_fill_q75_box_smart1.jpg b/categories/matter/index_hue83b50b66d2879f78d068a069bf95e8c_68735_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..5d597cc5b Binary files /dev/null and b/categories/matter/index_hue83b50b66d2879f78d068a069bf95e8c_68735_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/matter/page/1/index.html b/categories/matter/page/1/index.html new file mode 100644 index 000000000..bc671eba2 --- /dev/null +++ b/categories/matter/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/matter/ + \ No newline at end of file diff --git a/categories/matter/page/2/index.html b/categories/matter/page/2/index.html new file mode 100644 index 000000000..05ff4f699 --- /dev/null +++ b/categories/matter/page/2/index.html @@ -0,0 +1,56 @@ +Category: Matter - Pager 2 - kurisaW +

Categories

8 pages

Matter

Matter 是一个统一的开源应用层连接标准,旨在使开发人员和设备制造商能够连接和构建可靠、安全的生态系统,并提高互联家庭设备之间的兼容性。

\ No newline at end of file diff --git a/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30.jpg b/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30.jpg new file mode 100644 index 000000000..f2f6b2a89 Binary files /dev/null and b/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30.jpg differ diff --git a/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30_hu9ac246440863c6bc974cd58c095e92d7_35811_250x150_fill_q75_box_smart1.jpg b/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30_hu9ac246440863c6bc974cd58c095e92d7_35811_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..5fd69452d Binary files /dev/null and b/categories/micro_ros/index.a171402b74961bf86c9760a9fb40da30_hu9ac246440863c6bc974cd58c095e92d7_35811_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/micro_ros/index.html b/categories/micro_ros/index.html new file mode 100644 index 000000000..bbcc7883d --- /dev/null +++ b/categories/micro_ros/index.html @@ -0,0 +1,55 @@ +Category: Micro_ROS - kurisaW +

Categories

1 page

Micro_ROS

micro-ROS是一个使用ROS2的机器人控制系统的开源项目,ROS2是第二代ROS(机器人操作系统),用于微控制器上的各种机器人系统。

\ No newline at end of file diff --git a/categories/micro_ros/index.jpg b/categories/micro_ros/index.jpg new file mode 100644 index 000000000..f2f6b2a89 Binary files /dev/null and b/categories/micro_ros/index.jpg differ diff --git a/categories/micro_ros/index.xml b/categories/micro_ros/index.xml new file mode 100644 index 000000000..6e6a1fbee --- /dev/null +++ b/categories/micro_ros/index.xml @@ -0,0 +1,472 @@ +Micro_ROS on kurisaWhttps://kurisaw.github.io/categories/micro_ros/Recent content in Micro_ROS on kurisaWHugo -- gohugo.ioenThu, 26 Oct 2023 00:00:00 +0000【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul> \ No newline at end of file diff --git a/categories/micro_ros/index_hu9ac246440863c6bc974cd58c095e92d7_35811_120x120_fill_q75_box_smart1.jpg b/categories/micro_ros/index_hu9ac246440863c6bc974cd58c095e92d7_35811_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..595dfa222 Binary files /dev/null and b/categories/micro_ros/index_hu9ac246440863c6bc974cd58c095e92d7_35811_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/micro_ros/page/1/index.html b/categories/micro_ros/page/1/index.html new file mode 100644 index 000000000..c70c38b7d --- /dev/null +++ b/categories/micro_ros/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/micro_ros/ + \ No newline at end of file diff --git "a/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd.jpg" "b/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd.jpg" new file mode 100644 index 000000000..1f7dcabf8 Binary files /dev/null and "b/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd.jpg" differ diff --git "a/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd_hu8202dd07a403bdf098b503dcb02791c9_7047_250x150_fill_q75_box_smart1.jpg" "b/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd_hu8202dd07a403bdf098b503dcb02791c9_7047_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..08e4deb41 Binary files /dev/null and "b/categories/nxp\345\255\246\344\271\240/index.a4e748301af1c4af47872da47857bccd_hu8202dd07a403bdf098b503dcb02791c9_7047_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/nxp\345\255\246\344\271\240/index.html" "b/categories/nxp\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..ad987d289 --- /dev/null +++ "b/categories/nxp\345\255\246\344\271\240/index.html" @@ -0,0 +1,55 @@ +Category: NXP学习 - kurisaW +

Categories

4 pages

NXP学习

恩智浦半导体公司(NXP Semiconductors)是一家半导体公司,于2006年成立,总部位于荷兰埃因霍温。公司提供半导体、系统解决方案和软体服务。本模块主要使用LPC家族的LPC55S69进行学习,欢迎交流讨论!

\ No newline at end of file diff --git "a/categories/nxp\345\255\246\344\271\240/index.jpg" "b/categories/nxp\345\255\246\344\271\240/index.jpg" new file mode 100644 index 000000000..1f7dcabf8 Binary files /dev/null and "b/categories/nxp\345\255\246\344\271\240/index.jpg" differ diff --git "a/categories/nxp\345\255\246\344\271\240/index.xml" "b/categories/nxp\345\255\246\344\271\240/index.xml" new file mode 100644 index 000000000..eb8550794 --- /dev/null +++ "b/categories/nxp\345\255\246\344\271\240/index.xml" @@ -0,0 +1,2127 @@ +NXP学习 on kurisaWhttps://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/Recent content in NXP学习 on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> \ No newline at end of file diff --git "a/categories/nxp\345\255\246\344\271\240/index_hu8202dd07a403bdf098b503dcb02791c9_7047_120x120_fill_q75_box_smart1.jpg" "b/categories/nxp\345\255\246\344\271\240/index_hu8202dd07a403bdf098b503dcb02791c9_7047_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..1e04fe824 Binary files /dev/null and "b/categories/nxp\345\255\246\344\271\240/index_hu8202dd07a403bdf098b503dcb02791c9_7047_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/nxp\345\255\246\344\271\240/page/1/index.html" "b/categories/nxp\345\255\246\344\271\240/page/1/index.html" new file mode 100644 index 000000000..9b3cfbe7e --- /dev/null +++ "b/categories/nxp\345\255\246\344\271\240/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/ + \ No newline at end of file diff --git a/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28.jpg b/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28.jpg new file mode 100644 index 000000000..5d16e7b85 Binary files /dev/null and b/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28.jpg differ diff --git a/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28_hu22b20d9d06309e7775b600e304d92a78_28633_250x150_fill_q75_box_smart1.jpg b/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28_hu22b20d9d06309e7775b600e304d92a78_28633_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..c7687b86d Binary files /dev/null and b/categories/operating_system/index.2fbc71771bc581c5a2547cce4c154e28_hu22b20d9d06309e7775b600e304d92a78_28633_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/operating_system/index.html b/categories/operating_system/index.html new file mode 100644 index 000000000..2f94e1980 --- /dev/null +++ b/categories/operating_system/index.html @@ -0,0 +1,55 @@ +Category: operating_system - kurisaW +

Categories

2 pages

operating_system

操作系统(英语operating system,缩写OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石。 操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。 操作系统也提供一个让用户与系统交互的操作界面。

\ No newline at end of file diff --git a/categories/operating_system/index.jpg b/categories/operating_system/index.jpg new file mode 100644 index 000000000..5d16e7b85 Binary files /dev/null and b/categories/operating_system/index.jpg differ diff --git a/categories/operating_system/index.xml b/categories/operating_system/index.xml new file mode 100644 index 000000000..05fcf28fe --- /dev/null +++ b/categories/operating_system/index.xml @@ -0,0 +1,254 @@ +operating_system on kurisaWhttps://kurisaw.github.io/categories/operating_system/Recent content in operating_system on kurisaWHugo -- gohugo.ioenThu, 10 Mar 2022 00:00:00 +0000信号量及PV操作详解https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/Thu, 10 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 信号量及PV操作详解" /><h2 id="信号量">信号量 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->一个特殊变量</li> +<li><!-- raw HTML omitted -->用于进程间传递信息的一个整数值</li> +</ul> +</blockquote> +<p>定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct semaphore +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int count; +</span></span><span class="line"><span class="cl"> quenue Type quenue; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<ul> +<li><!-- raw HTML omitted -->信号量说明:semaphore s;</li> +<li><!-- raw HTML omitted -->对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen))</li> +</ul> +</blockquote> +<h2 id="pv操作定义">P、V操作定义 +</h2><p><!-- raw HTML omitted -->P(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.count --; //信号量值减一 +</span></span><span class="line"><span class="cl"> if(s.count&lt;0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 该进程状态置为阻塞态; +</span></span><span class="line"><span class="cl"> 将该进程插入相应的等待队列s.quenue末尾; +</span></span><span class="line"><span class="cl"> 重新调度 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>down</code>,<code>semwait</code>:也代表P操作</p> +<p><!-- raw HTML omitted -->V(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.ount++; +</span></span><span class="line"><span class="cl"> if(s.count&lt;=0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 唤醒相应等待队列s.queue中等待的一个进程; +</span></span><span class="line"><span class="cl"> 改变其状态为就绪态,并将其插入就绪队列; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>up</code>,<code>semsignal</code>:也代表V操作</p> +<blockquote> +<p>相关说明</p> +<ul> +<li><!-- raw HTML omitted -->P,V操作为原语操作</li> +<li><!-- raw HTML omitted -->在信号量上定义了三个操作 +<!-- raw HTML omitted -->初始化(非负数)、P操作、V操作<!-- raw HTML omitted --></li> +<li><!-- raw HTML omitted -->最初提出的是二元信号量(解决互斥) +之后,推广到一般信号量(多值)或技术信号量(解决同步)</li> +</ul> +</blockquote> +<h2 id="用pv操作解决进程间互斥问题">用PV操作解决进程间互斥问题 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->分析并发进程的关键活动,划定临界区</li> +<li><!-- raw HTML omitted -->设置信号量mutux,初值为1</li> +<li><!-- raw HTML omitted -->在临界区前实施P(mutux)</li> +<li><!-- raw HTML omitted -->在临界区之后实施V(mutux)</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/9f7d7a26cf6a41048d7205423383fa64.png" +loading="lazy" +alt="图片演示" +></p> +<blockquote> +<p>相关解释:</p> +</blockquote> +<ul> +<li> +<p><code>临界区</code> : 我们把并发进程中与共享变量有关的程序段称为临界区。</p> +</li> +<li> +<p><code>信号量</code> : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。</p> +</li> +<li> +<p><code>进程的互斥</code>:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。</p> +</li> +<li> +<p><code>进程的同步</code>:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。</p> +</li> +<li> +<p><code>pv操作又称wait,signal原语。</code> +主要是操作进程中对进程控制的信息量的加减控制。</p> +</li> +</ul> +<blockquote> +<p><!-- raw HTML omitted --><code>注意:</code>在霍尔管程中,<code>wait操作</code>和<code>signal操作</code>用于被设计为两个可以中断的过程,而非<code>原语。</code> +<!-- raw HTML omitted -->在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 +条件变量的两种操作:</p> +<ul> +<li>wait()操作<!-- raw HTML omitted -->[阻塞调用进程]<!-- raw HTML omitted --></li> +<li>signal()操作<!-- raw HTML omitted -->[释放/唤醒在条件变量上阻塞的进程]<!-- raw HTML omitted --></li> +</ul> +</blockquote> +<ul> +<li>wait用法: +wait(num),num是目标参数,wait的作用是使其(信息量)减一。 +如果信息量&gt;=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 +signal用法: +signal(num),num是目标参数,signal的作用是使其(信息量)加一。 +如果信息量&gt;0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。</li> +</ul> +<blockquote> +<p>本文资源来自<a class="link" href="https://www.coursera.org/learn/os-pku" target="_blank" rel="noopener" +>Operating Systems</a> +参考:<a class="link" href="https://blog.csdn.net/thebestway/article/details/105034840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164992015416780255296134%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=164992015416780255296134&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-105034840.142%5ev8%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=wait%E5%92%8Csignal%E5%8E%9F%E8%AF%AD&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>操作系统P,V(wait,signal原语)操作讲解</a></p> +</blockquote>进程上下文和线程上下文https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/Tue, 08 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/cover.jpg" alt="Featured image of post 进程上下文和线程上下文" /><h2 id="进程">进程 +</h2><p><code>操作系统资源分配的基本单位</code>,也就是指计算机中已执行的程序。</p> +<ul> +<li>在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,<code>进程</code>是程序的基本执行实体;</li> +<li>在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是<code>线程</code>的容器。</li> +<li>程序本身只是指令、数据及其组织形式的描述,相当于一个名词,<code>进程</code>才是程序(那些指令和数据)的真正<code>执行实例</code>.</li> +</ul> +<h2 id="进程上下文">进程上下文 +</h2><p><code>进程上下文</code>就是表示<code>进程信息</code>的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。</p> +<p>拿<code>Linux进程</code>举例: +&mdash;-进程的运行环境主要包括:</p> +<blockquote> +<p>1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 +2.环境变量:提供进程运行所需的环境信息。 +3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 +4.进程访问设备或者文件时的权限。 +5.各种硬件寄存器。 +6.地址转换信息。</p> +</blockquote> +<p>由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。</p> +<h2 id="线程">线程 +</h2><p><code>操作系统能够进行运算调度的最小单位</code>。</p> +<ul> +<li>大部分情况下,它被包含在进程之中,是进程中的实际运作单位。</li> +<li>一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。</li> +<li>线程是独立调度和分派的基本单位。 +线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。</li> +<li>同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。</li> +</ul> +<h2 id="线程上下文">线程上下文 +</h2><p>进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。<code>同样的,线程也有上下文。</code></p> +<blockquote> +<p>当线程被抢占时,就会发生线程之间的上下文切换。 +如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。</p> +</blockquote> +<p>线程上下文与进程上下文对比</p> +<table> +<thead> +<tr> +<th>上下文内容</th> +<th>进程</th> +<th>线程</th> +</tr> +</thead> +<tbody> +<tr> +<td>指向可执行文件的指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>栈</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>内存(数据段和堆)</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>状态</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>优先级</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>程序IO的状态</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>授予权限</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>调度信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>审计信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件描述符</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件读/写指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>寄存器组</td> +<td>×</td> +<td>×</td> +</tr> +</tbody> +</table> \ No newline at end of file diff --git a/categories/operating_system/index_hu22b20d9d06309e7775b600e304d92a78_28633_120x120_fill_q75_box_smart1.jpg b/categories/operating_system/index_hu22b20d9d06309e7775b600e304d92a78_28633_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..896f3eac9 Binary files /dev/null and b/categories/operating_system/index_hu22b20d9d06309e7775b600e304d92a78_28633_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/operating_system/page/1/index.html b/categories/operating_system/page/1/index.html new file mode 100644 index 000000000..a1d0bc718 --- /dev/null +++ b/categories/operating_system/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/operating_system/ + \ No newline at end of file diff --git a/categories/page/1/index.html b/categories/page/1/index.html new file mode 100644 index 000000000..5d79fa45e --- /dev/null +++ b/categories/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/ + \ No newline at end of file diff --git a/categories/page/2/index.html b/categories/page/2/index.html new file mode 100644 index 000000000..1886560b9 --- /dev/null +++ b/categories/page/2/index.html @@ -0,0 +1,57 @@ +Categories +

Section

15 pages

Categories

\ No newline at end of file diff --git a/categories/page/3/index.html b/categories/page/3/index.html new file mode 100644 index 000000000..00119e8b1 --- /dev/null +++ b/categories/page/3/index.html @@ -0,0 +1,57 @@ +Categories +

Section

15 pages

Categories

\ No newline at end of file diff --git a/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71.jpg b/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71.jpg new file mode 100644 index 000000000..678a5fbcb Binary files /dev/null and b/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71.jpg differ diff --git a/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_250x150_fill_q75_box_smart1.jpg b/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_250x150_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..672ffdf19 Binary files /dev/null and b/categories/rt-thread/index.2ab8ee7dc723db90ac670871f605fc71_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_250x150_fill_q75_box_smart1.jpg differ diff --git a/categories/rt-thread/index.html b/categories/rt-thread/index.html new file mode 100644 index 000000000..35ca497ff --- /dev/null +++ b/categories/rt-thread/index.html @@ -0,0 +1,57 @@ +Category: RT-Thread - kurisaW +

Categories

13 pages

RT-Thread

RT-Thread 是一款主要由中国开源社区主导开发的开源实时操作系统(v3.1.0以及以前版本遵循GPLv2+许可协议,v3.1.0以后版本遵循 Apache License 2.0 开源许可协议)。实时线程操作系统不仅仅是一个单一的实时操作系统内核,它也是一个完整的应用系统,包含了实时、嵌入式系统相关的各个组件:TCP/IP协议栈,libc接口,图形用户界面等。

\ No newline at end of file diff --git a/categories/rt-thread/index.jpg b/categories/rt-thread/index.jpg new file mode 100644 index 000000000..678a5fbcb Binary files /dev/null and b/categories/rt-thread/index.jpg differ diff --git a/categories/rt-thread/index.xml b/categories/rt-thread/index.xml new file mode 100644 index 000000000..b44f72cca --- /dev/null +++ b/categories/rt-thread/index.xml @@ -0,0 +1,7701 @@ +RT-Thread on kurisaWhttps://kurisaw.github.io/categories/rt-thread/Recent content in RT-Thread on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduinohttps://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover.jpg" alt="Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino" /><h1 id="瑞萨hmi-board使用vscode开发rtduino结合ssd1306-oled">瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) +</h1><hr> +<h2 id="1准备工作">1.准备工作 +</h2><p>软件环境:</p> +<ul> +<li><a class="link" href="https://github.com/RT-Thread/rt-thread" target="_blank" rel="noopener" +> RT-Thread 主仓代码(需下载至本地)</a></li> +<li>vscode</li> +<li>rt-thread env</li> +</ul> +<p>硬件环境:</p> +<ul> +<li>RA6M3-HMI-Board 开发板</li> +<li>0.96寸 ssd1306 oled 显示屏</li> +</ul> +<h2 id="2工程配置">2.工程配置 +</h2><p>首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要我们提前安装好 ENV 环境,具体细节请参考 <a class="link" href="https://docs.rtduino.com/#/zh/beginner/env?id=env%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba" target="_blank" rel="noopener" +>Env编译环境搭建</a> 。</p> +<p>鼠标右键打开 ENV 工具后,使用 <strong>menuconfig</strong> 命令打开可视化菜单,勾选上 <strong>RTduino</strong> 的使能项,保存并退出</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251.png" +width="1086" +height="392" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123170636251" +class="gallery-image" +data-flex-grow="277" +data-flex-basis="664px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">RT-Thread Configuration +</span></span><span class="line"><span class="cl"> → Hardware Drivers Config +</span></span><span class="line"><span class="cl"> → Onboard Peripheral Drivers +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Compatible with Arduino Ecosystem <span class="o">(</span>RTduino<span class="o">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123171151275" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623.png" +width="1682" +height="768" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173108623" +class="gallery-image" +data-flex-grow="219" +data-flex-basis="525px" +></p> +<h2 id="3开始编译">3.开始编译 +</h2><p>打开 ENV ,同时执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons -j16 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173509831" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>在工程编译完成后会生成一个 <code>.elf</code>后缀的可执行文件,到这里工程的编译就顺利结束了。</p> +<h2 id="4vscode调试配置">4.vscode调试配置 +</h2><p>首先我们需要在 vscode 中安装 <code>Cortex-Debug</code> 插件,打开 vscode 扩展,搜索 <code>Cortex-Debug</code>并安装扩展:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123175244073" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接下来就是安装 <code>pyocd</code> 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 <code>create a launch.json file</code>:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889.png" +width="1385" +height="462" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123180230889" +class="gallery-image" +data-flex-grow="299" +data-flex-basis="719px" +></p> +<p>之后 vscode 会创建一份 <code>launch.json</code> 文件,我们需要替换文件内容为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// Use IntelliSense to learn about possible attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Hover to view descriptions of existing attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.2.0&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;configurations&#34;</span><span class="p">:</span> <span class="p">[</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;HMI-Board&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;cwd&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceFolder}&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;executable&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;request&#34;</span><span class="p">:</span> <span class="s2">&#34;launch&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;cortex-debug&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;runToEntryPoint&#34;</span><span class="p">:</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;targetId&#34;</span><span class="p">:</span> <span class="s2">&#34;R7FA6M3AH&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;servertype&#34;</span><span class="p">:</span> <span class="s2">&#34;pyocd&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;serverpath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/compile/sdk-debugger-pyocd/pyocd.bat&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;armToolchainPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;gdbPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<code>launch.json</code>文件中的部分参数需要根据具体位置配置</p> +<ul> +<li><code>serverpath</code>:这部分路径在前面所安装的 <code>sdk-debugger-pyocd</code>位置</li> +<li><code>armToolchainPath</code>:gcc 工具链,找不到位置的可以<a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>点击此处下载</a></li> +<li><code>gdbPath</code></li> +</ul> +<p>在完成上述配置后就可以点击 <code>F5</code> 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123183906784" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932.png" +width="815" +height="536" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184032932" +class="gallery-image" +data-flex-grow="152" +data-flex-basis="364px" +></p> +<p>到这里 RTduino 就已经成功运行在 RT-Thread 啦!</p> +<h2 id="5demo使用-rtduino-驱动-096寸-ssd1306-oled">5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled +</h2><p>在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过<code>RTduino</code>,并在<code>RT-Thread</code>中使用 <code>Arduino</code> 源码驱动一个 oled 屏幕。</p> +<p>我们接着回到 ENV 中,使用 <code>menuconfig</code>命令打开菜单,同时使用 <code>shift + /</code>打开搜索界面,并且输入:<code>ssd1306</code>关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 <code>Adafruit SSD1306</code>对应的 <code>2</code>选项,进入点击 <code>y</code> 使能:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184834403" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184930394" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p>这样我们就成功把 <code>Adafruit SSD1306</code> 示例库下载到本地了,同时还有一下依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453.png" +width="1720" +height="772" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123185120453" +class="gallery-image" +data-flex-grow="222" +data-flex-basis="534px" +></p> +<p>我们找到路径:<code>rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c</code>,可以看到该文件夹下有一个<code>ssd1306_128x64_i2c.ino</code>文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的<code>arduino_main.cpp</code>文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board<span class="se">\b</span>oard<span class="se">\r</span>tduino<span class="se">\a</span>rduino_main.cpp +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span><span class="lnt">267 +</span><span class="lnt">268 +</span><span class="lnt">269 +</span><span class="lnt">270 +</span><span class="lnt">271 +</span><span class="lnt">272 +</span><span class="lnt">273 +</span><span class="lnt">274 +</span><span class="lnt">275 +</span><span class="lnt">276 +</span><span class="lnt">277 +</span><span class="lnt">278 +</span><span class="lnt">279 +</span><span class="lnt">280 +</span><span class="lnt">281 +</span><span class="lnt">282 +</span><span class="lnt">283 +</span><span class="lnt">284 +</span><span class="lnt">285 +</span><span class="lnt">286 +</span><span class="lnt">287 +</span><span class="lnt">288 +</span><span class="lnt">289 +</span><span class="lnt">290 +</span><span class="lnt">291 +</span><span class="lnt">292 +</span><span class="lnt">293 +</span><span class="lnt">294 +</span><span class="lnt">295 +</span><span class="lnt">296 +</span><span class="lnt">297 +</span><span class="lnt">298 +</span><span class="lnt">299 +</span><span class="lnt">300 +</span><span class="lnt">301 +</span><span class="lnt">302 +</span><span class="lnt">303 +</span><span class="lnt">304 +</span><span class="lnt">305 +</span><span class="lnt">306 +</span><span class="lnt">307 +</span><span class="lnt">308 +</span><span class="lnt">309 +</span><span class="lnt">310 +</span><span class="lnt">311 +</span><span class="lnt">312 +</span><span class="lnt">313 +</span><span class="lnt">314 +</span><span class="lnt">315 +</span><span class="lnt">316 +</span><span class="lnt">317 +</span><span class="lnt">318 +</span><span class="lnt">319 +</span><span class="lnt">320 +</span><span class="lnt">321 +</span><span class="lnt">322 +</span><span class="lnt">323 +</span><span class="lnt">324 +</span><span class="lnt">325 +</span><span class="lnt">326 +</span><span class="lnt">327 +</span><span class="lnt">328 +</span><span class="lnt">329 +</span><span class="lnt">330 +</span><span class="lnt">331 +</span><span class="lnt">332 +</span><span class="lnt">333 +</span><span class="lnt">334 +</span><span class="lnt">335 +</span><span class="lnt">336 +</span><span class="lnt">337 +</span><span class="lnt">338 +</span><span class="lnt">339 +</span><span class="lnt">340 +</span><span class="lnt">341 +</span><span class="lnt">342 +</span><span class="lnt">343 +</span><span class="lnt">344 +</span><span class="lnt">345 +</span><span class="lnt">346 +</span><span class="lnt">347 +</span><span class="lnt">348 +</span><span class="lnt">349 +</span><span class="lnt">350 +</span><span class="lnt">351 +</span><span class="lnt">352 +</span><span class="lnt">353 +</span><span class="lnt">354 +</span><span class="lnt">355 +</span><span class="lnt">356 +</span><span class="lnt">357 +</span><span class="lnt">358 +</span><span class="lnt">359 +</span><span class="lnt">360 +</span><span class="lnt">361 +</span><span class="lnt">362 +</span><span class="lnt">363 +</span><span class="lnt">364 +</span><span class="lnt">365 +</span><span class="lnt">366 +</span><span class="lnt">367 +</span><span class="lnt">368 +</span><span class="lnt">369 +</span><span class="lnt">370 +</span><span class="lnt">371 +</span><span class="lnt">372 +</span><span class="lnt">373 +</span><span class="lnt">374 +</span><span class="lnt">375 +</span><span class="lnt">376 +</span><span class="lnt">377 +</span><span class="lnt">378 +</span><span class="lnt">379 +</span><span class="lnt">380 +</span><span class="lnt">381 +</span><span class="lnt">382 +</span><span class="lnt">383 +</span><span class="lnt">384 +</span><span class="lnt">385 +</span><span class="lnt">386 +</span><span class="lnt">387 +</span><span class="lnt">388 +</span><span class="lnt">389 +</span><span class="lnt">390 +</span><span class="lnt">391 +</span><span class="lnt">392 +</span><span class="lnt">393 +</span><span class="lnt">394 +</span><span class="lnt">395 +</span><span class="lnt">396 +</span><span class="lnt">397 +</span><span class="lnt">398 +</span><span class="lnt">399 +</span><span class="lnt">400 +</span><span class="lnt">401 +</span><span class="lnt">402 +</span><span class="lnt">403 +</span><span class="lnt">404 +</span><span class="lnt">405 +</span><span class="lnt">406 +</span><span class="lnt">407 +</span><span class="lnt">408 +</span><span class="lnt">409 +</span><span class="lnt">410 +</span><span class="lnt">411 +</span><span class="lnt">412 +</span><span class="lnt">413 +</span><span class="lnt">414 +</span><span class="lnt">415 +</span><span class="lnt">416 +</span><span class="lnt">417 +</span><span class="lnt">418 +</span><span class="lnt">419 +</span><span class="lnt">420 +</span><span class="lnt">421 +</span><span class="lnt">422 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/* +</span></span><span class="line"><span class="cl"> * Copyright <span class="o">(</span>c<span class="o">)</span> 2006-2023, RT-Thread Development Team +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * SPDX-License-Identifier: Apache-2.0 +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * Change Logs: +</span></span><span class="line"><span class="cl"> * Date Author Notes +</span></span><span class="line"><span class="cl"> * 2023-10-28 Wangyuqiang first version +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Arduino.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;SPI.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Wire.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_GFX.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_SSD1306.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_WIDTH 128 // OLED display width, in pixels</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_HEIGHT 64 // OLED display height, in pixels</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// Declaration <span class="k">for</span> an SSD1306 display connected to I2C <span class="o">(</span>SDA, SCL pins<span class="o">)</span> +</span></span><span class="line"><span class="cl">// The pins <span class="k">for</span> I2C are defined by the Wire-library. +</span></span><span class="line"><span class="cl">// On an arduino UNO: A4<span class="o">(</span>SDA<span class="o">)</span>, A5<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino MEGA 2560: 20<span class="o">(</span>SDA<span class="o">)</span>, 21<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino LEONARDO: 2<span class="o">(</span>SDA<span class="o">)</span>, 3<span class="o">(</span>SCL<span class="o">)</span>, ... +</span></span><span class="line"><span class="cl"><span class="c1">#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_ADDRESS 0x3C ///&lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32</span> +</span></span><span class="line"><span class="cl">Adafruit_SSD1306 display<span class="o">(</span>SCREEN_WIDTH, SCREEN_HEIGHT, <span class="p">&amp;</span>Wire, OLED_RESET<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define NUMFLAKES 10 // Number of snowflakes in the animation example</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_HEIGHT 16</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_WIDTH 16</span> +</span></span><span class="line"><span class="cl">static const unsigned char PROGMEM logo_bmp<span class="o">[]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="o">{</span> 0b00000000, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11110011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11111110, 0b11111000, +</span></span><span class="line"><span class="cl"> 0b01111110, 0b11111111, +</span></span><span class="line"><span class="cl"> 0b00110011, 0b10011111, +</span></span><span class="line"><span class="cl"> 0b00011111, 0b11111100, +</span></span><span class="line"><span class="cl"> 0b00001101, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00011011, 0b10100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01111100, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01110000, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00000000, 0b00110000 <span class="o">}</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void setup<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.begin<span class="o">(</span>115200<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // <span class="nv">SSD1306_SWITCHCAPVCC</span> <span class="o">=</span> generate display voltage from 3.3V internally +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span>!display.begin<span class="o">(</span>SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS<span class="o">))</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;SSD1306 allocation failed&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span><span class="p">;</span> // Don<span class="s1">&#39;t proceed, loop forever +</span></span></span><span class="line"><span class="cl"><span class="s1"> } +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show initial display buffer contents on the screen -- +</span></span></span><span class="line"><span class="cl"><span class="s1"> // the library initializes this with an Adafruit splash screen. +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); // Pause for 2 seconds +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Clear the buffer +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.clearDisplay(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Draw a single pixel in white +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.drawPixel(10, 10, SSD1306_WHITE); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show the display buffer on the screen. You MUST call display() after +</span></span></span><span class="line"><span class="cl"><span class="s1"> // drawing commands to make them visible on screen! +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); +</span></span></span><span class="line"><span class="cl"><span class="s1"> // display.display() is NOT necessary after every single drawing command, +</span></span></span><span class="line"><span class="cl"><span class="s1"> // unless that&#39;</span>s what you want...rather, you can batch up a bunch of +</span></span><span class="line"><span class="cl"> // drawing operations and <span class="k">then</span> update the screen all at once by calling +</span></span><span class="line"><span class="cl"> // display.display<span class="o">()</span>. These examples demonstrate both approaches... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawtriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfilltriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawchar<span class="o">()</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawstyles<span class="o">()</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testscrolltext<span class="o">()</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawbitmap<span class="o">()</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Invert and restore display, pausing in-between +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">false</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testanimate<span class="o">(</span>logo_bmp, LOGO_WIDTH, LOGO_HEIGHT<span class="o">)</span><span class="p">;</span> // Animate bitmaps +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void loop<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int16_t i<span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn line +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.width<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> <span class="m">2</span> seconds +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so rectangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-i*2, display.height<span class="o">()</span>-i*2, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawCircle<span class="o">(</span>display.width<span class="o">()</span>/2, display.height<span class="o">()</span>/2, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so circles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillCircle<span class="o">(</span>display.width<span class="o">()</span> / 2, display.height<span class="o">()</span> / 2, i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn circle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so round-rects alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so triangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0, 0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.cp437<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> // Use full <span class="m">256</span> char <span class="s1">&#39;Code Page 437&#39;</span> font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Not all the characters will fit on the display. This is normal. +</span></span><span class="line"><span class="cl"> // Library will draw what it can and the rest will be clipped. +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;256<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span><span class="nv">i</span> <span class="o">==</span> <span class="s1">&#39;\n&#39;</span><span class="o">)</span> display.write<span class="o">(</span><span class="s1">&#39; &#39;</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> display.write<span class="o">(</span>i<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0,0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_BLACK, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;inverse&#39;</span> text +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>3.141592<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;0x&#34;</span><span class="o">))</span><span class="p">;</span> display.println<span class="o">(</span>0xDEADBEEF, HEX<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>10, 0<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;scroll&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show initial text +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>100<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Scroll in various directions, pausing in-between: +</span></span><span class="line"><span class="cl"> display.startscrollright<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrollleft<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagright<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagleft<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span> +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.width<span class="o">()</span> - LOGO_WIDTH <span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.height<span class="o">()</span> - LOGO_HEIGHT<span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define XPOS 0 // Indexes into the &#39;icons&#39; array in function below</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define YPOS 1</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define DELTAY 2</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int8_t f, icons<span class="o">[</span>NUMFLAKES<span class="o">][</span>3<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Initialize <span class="s1">&#39;snowflake&#39;</span> positions +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;x: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; y: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; dy: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span> <span class="o">{</span> // Loop forever... +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear the display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Draw each snowflake: +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, bitmap, w, h, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show the display buffer on the screen +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>200<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> 1/10 second +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Then update coordinates of each flake... +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> +<span class="o">=</span> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> // If snowflake is off the bottom of the screen... +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> &gt;<span class="o">=</span> display.height<span class="o">())</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // Reinitialize to a random position, just off the top +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在此示例中有几点注意事项:</p> +<ul> +<li>在每一份添加的示例工程中,我们都必须要包含头文件 <code>#include &lt;Arduino.h&gt;</code></li> +<li>由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 <code>0x3c</code>,所以对应示例工程中的 <code>SCREEN_ADDRESS</code>需要修改为 <code>0X3C</code></li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061.png" +width="533" +height="143" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190157061" +class="gallery-image" +data-flex-grow="372" +data-flex-basis="894px" +></p> +<ul> +<li>由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍</li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190348607" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:</p> +<table> +<thead> +<tr> +<th style="text-align:center">pin</th> +<th style="text-align:center">func</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">P203</td> +<td style="text-align:center">i2c0-sda</td> +</tr> +<tr> +<td style="text-align:center">P202</td> +<td style="text-align:center">i2c0-scl</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">vcc</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">gnd</td> +</tr> +</tbody> +</table> +<p>接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695.png" +width="813" +height="431" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123191534695" +class="gallery-image" +data-flex-grow="188" +data-flex-basis="452px" +></p> +<p>查看demo:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo.gif" +width="1280" +height="720" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif 1024w" +loading="lazy" +alt="demo" +class="gallery-image" +data-flex-grow="177" +data-flex-basis="426px" +></p>RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div>RT-Thread内核宏定义详解(rtdef.h)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/Sun, 09 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/cover.jpg" alt="Featured image of post RT-Thread内核宏定义详解(rtdef.h)" /><h4 id="1rt-thread版本信息">1.RT-Thread版本信息 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread version information */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_VERSION 4 </span><span class="cm">/**&lt; major version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SUBVERSION 1 </span><span class="cm">/**&lt; minor version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_REVISION 1 </span><span class="cm">/**&lt; revise version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread version */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>使用方法:可用于bsp指定RT-Thread版本</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#if (RTTHREAD_VERSION &gt;= RT_VERSION_CHECK(4, 1, 0) */ +</span></span><span class="line"><span class="cl">#define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \ +</span></span><span class="line"><span class="cl"> (minor * 100) + revise) +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2rt-thrad基础数据类型定义">2.RT-Thrad基础数据类型定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread basic data type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_ARCH_DATA_TYPE </span><span class="cm">/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC </span><span class="cm">/* 用于控制是否使用标准C库函数 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">int8_t</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int16_t</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int32_t</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint8_t</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint16_t</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint32_t</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int64_t</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint64_t</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">size_t</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">char</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">short</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">int</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef ARCH_CPU_64BIT </span><span class="cm">/* 判断当前程序运行的CPU架构是否为64位 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* ARCH_CPU_64BIT */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_ARCH_DATA_TYPE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int</span> <span class="kt">rt_bool_t</span><span class="p">;</span> <span class="cm">/**&lt; boolean type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">rt_base_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit CPU related date type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_ubase_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit unsigned CPU related data type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_err_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for error number */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_time_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for time stamp */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_tick_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for tick count */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_flag_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for flags */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_ubase_t</span> <span class="kt">rt_dev_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for device */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_off_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for offset */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* boolean type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TRUE 1 </span><span class="cm">/**&lt; boolean true */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_FALSE 0 </span><span class="cm">/**&lt; boolean fails */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* null pointer definition */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_NULL 0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p><code>rt_base_t</code>:为了使代码可以<strong>在不同的CPU上移植并保持向后兼容性</strong>。<code>long</code>类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用<code>rt_base_t</code>代替<code>long</code>可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)</p> +</li> +<li> +<p><code>rt_err_t</code>:代表<strong>错误码</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_time_t</code>:代表<strong>时间戳</strong>的数据类型,这里使用了<code>rt_uint32_t</code>作为它的别名。<code>rt_uint32_t</code>是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。</p> +</li> +<li> +<p><code>rt_tick_t</code>:代表<strong>系统时钟节拍计数</strong>的数据类型,这里也使用了<code>rt_uint32_t</code>作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对<code>rt_tick_t</code>进行递增操作,从而实现对时间的计数。</p> +</li> +<li> +<p><code>rt_flag_t</code>:代表<strong>标志位</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_dev_t</code>:代表<strong>设备号</strong>的数据类型,这里使用了<code>rt_ubase_t</code>作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。</p> +</li> +<li> +<p><code>rt_off_t</code>:代表<strong>偏移量</strong>的数据类型,这里也使用了之前定义的<code>rt_base_t</code>作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。</p> +</li> +</ul> +<h4 id="3rt-thread基本数据类型的范围">3.RT-Thread基本数据类型的范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of base type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX UINT8_MAX </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX UINT16_MAX </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX UINT32_MAX </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX 0xff </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX 0xffff </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX 0xffffffff </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:此处的<code>UINT8_MAX</code>、<code>UINT16_MAX</code>、<code>UINT32_MAX</code>为编译器预定的宏定义</p> +<h4 id="4rt-thread系统滴答时钟最大计数值">4.RT-Thread系统滴答时钟最大计数值 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TICK_MAX RT_UINT32_MAX </span><span class="cm">/**&lt; Maximum number of tick */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5rt-thread-ipc数据类型范围">5.RT-Thread IPC数据类型范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of ipc type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SEM_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of semaphore .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mutex .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_HOLD_MAX RT_UINT8_MAX </span><span class="cm">/**&lt; Maximum number of mutex .hold */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MB_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mailbox .entry */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MQ_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of message queue .entry */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6rt-thread避免未使用变量警告">6.RT-Thread避免未使用变量警告 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_UNUSED(x) ((void)x) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>**该宏定义表示将变量x强制转换为<code>void</code>类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **</p> +<p>下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。</p> +<p>该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。</p> +<p>在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。</p> +<p>这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* sort code */</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">cmp</span><span class="p">);</span> <span class="c1">// 必须传递一个void*类型参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">b</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就可以避免编译器报“未使用变量a/b”的警告了。</p> +<h4 id="7编译器相关定义">7.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_SECTION(x)</code>:表示<strong>将所修饰的数据/函数放置在指定的section中</strong>,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。</li> +<li><code>RT_USED</code>:表示<strong>告诉编译器保留所修饰的数据/函数</strong>,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。</li> +<li><code>ALIGN(n)</code>:表示<strong>将所修饰的数据/函数按照n字节对齐</strong>,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。</li> +<li><code>RT_WEAK</code>:表示<strong>将所修饰的数据/函数标记为弱引用</strong>,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。</li> +<li><code>rt_inline</code>:表示<strong>将所修饰的函数定义为静态内联函数</strong>,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。</li> +</ul> +<h4 id="8编译器相关定义">8.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* module compiling */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_MODULE +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllimport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllexport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_MODULE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__IAR_SYSTEMS_ICC__) </span><span class="cm">/* for IAR Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) @ x +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __root +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) PRAGMA(data_alignment=n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __weak +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__GNUC__) </span><span class="cm">/* GNU GCC Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* the version of GNU GCC must be greater than 4.x */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__builtin_va_list</span> <span class="n">__gnuc_va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__gnuc_va_list</span> <span class="n">va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define va_start(v,l) __builtin_va_start(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_end(v) __builtin_va_end(v) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_arg(v,l) __builtin_va_arg(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__ADSPBLACKFIN__) </span><span class="cm">/* for VisualDSP++ Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (_MSC_VER) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __declspec(align(n)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TI_COMPILER_VERSION__) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* The way that TI compiler set section is different from other(at least +</span></span></span><span class="line"><span class="cl"><span class="cm"> * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more +</span></span></span><span class="line"><span class="cl"><span class="cm"> * details. */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TASKING__) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used, protect)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((__align(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="cp">#error not supported tool chain +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* __ARMCC_VERSION */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ol> +<li><code>typedef __builtin_va_list __gnuc_va_list</code>: 定义了一个新类型<code>__gnuc_va_list</code>,并使用 <code>__builtin_va_list</code> 进行初始化。<code>__builtin_va_list</code> 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 <code>__builtin_va_list</code> 类型来实现可变参数列表。</li> +<li><code>typedef __gnuc_va_list va_list</code>: 定义了一个名为<code>va_list</code>的新类型,并将其重命名为<code>__gnuc_va_list</code>。</li> +<li><code>#define va_start(v,l) __builtin_va_start(v,l)</code>: 将 <code>va_start()</code> 重命名为 <code>__builtin_va_start()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_start()</code> 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。</li> +<li><code>#define va_end(v) __builtin_va_end(v)</code>: 将 <code>va_end()</code> 重命名为 <code>__builtin_va_end()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_end()</code> 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。</li> +<li><code>#define va_arg(v,l) __builtin_va_arg(v,l)</code>: 将 <code>va_arg()</code> 重命名为 <code>__builtin_va_arg()</code>,并使用 GCC 内建的函数 <code>__builtin_va_arg()</code> 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。</li> +<li><code>#define PRAGMA(x) _Pragma(#x)</code>:将参数<code>x</code>转化为字符串并使用<code>_Pragma()</code>将其作为编译指令执行。<code>_Pragma</code>是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而<code>#pragma</code>则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。</li> +</ol> +<h4 id="9rt-thread错误码定义">9.RT-Thread错误码定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread error code definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_EOK 0 </span><span class="cm">/**&lt; There is no error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ERROR 1 </span><span class="cm">/**&lt; A generic error happens */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ETIMEOUT 2 </span><span class="cm">/**&lt; Timed out */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EFULL 3 </span><span class="cm">/**&lt; The resource is full */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EEMPTY 4 </span><span class="cm">/**&lt; The resource is empty */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOMEM 5 </span><span class="cm">/**&lt; No memory */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOSYS 6 </span><span class="cm">/**&lt; No system */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EBUSY 7 </span><span class="cm">/**&lt; Busy */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EIO 8 </span><span class="cm">/**&lt; IO error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINTR 9 </span><span class="cm">/**&lt; Interrupted system call */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINVAL 10 </span><span class="cm">/**&lt; Invalid argument */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_EOK</code>:表示没有错误。</li> +<li><code>RT_ERROR</code>:表示发生了一般性的错误。</li> +<li><code>RT_ETIMEOUT</code>:表示超时错误。</li> +<li><code>RT_EFULL</code>:表示资源已满。</li> +<li><code>RT_EEMPTY</code>:表示资源为空。</li> +<li><code>RT_ENOMEM</code>:表示内存不足。</li> +<li><code>RT_ENOSYS</code>:表示没有该系统。</li> +<li><code>RT_EBUSY</code>:表示忙碌。</li> +<li><code>RT_EIO</code>:表示输入/输出错误。</li> +<li><code>RT_EINTR</code>:表示中断的系统调用。</li> +<li><code>RT_EINVAL</code>:表示无效的参数。</li> +</ul>瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/Mon, 22 Aug 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/<img src="https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/cover.jpg" alt="Featured image of post 瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包" /><h4 id="一创建工程选择segger_rtt软件包">一、创建工程,选择SEGGER_RTT软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/015bb29dd26648570d03e65cd419f972.png" +loading="lazy" +alt="image-20221003133030692" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fb34abd8ec95bf35f09fb3bcde1f5d1d.png" +loading="lazy" +alt="image-20221003133219108" +></p> +<h4 id="2添加jlinkrtt初始化函数-路径rt-threadsrckservicec-">2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ] +</h4><p>在<code>rt_console_set_device</code>前调用<code>rt_hw_jlink_rtt_init</code>初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/492ff3b5ab1bf24e62a4380f3d47bf29.png" +loading="lazy" +alt="image-20221003133721333" +></p> +<h4 id="3控制台对接上jlinkrtt">3、控制台对接上jlinkRtt +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rtconfg.h +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// 修改RT_CONSOLE_DEVICE_NAME为空 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/img_convert/a4101391c61fad4add9376b4ebcd71e9.png" +loading="lazy" +alt="image-20221003134935152" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">shell</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="nl">D</span><span class="p">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">components</span><span class="err">\</span><span class="n">finsh</span><span class="err">\</span><span class="n">shell</span><span class="p">.</span><span class="n">c</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 1、首先添加以下头文件 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT_Conf.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 2、修改finsh_getchar */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">finsh_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_DEVICE +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">char</span> <span class="n">ch</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_POSIX_STDIO +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span><span class="p">(</span><span class="nf">read</span><span class="p">(</span><span class="n">STDIN_FILENO</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="cm">/* EOF */</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">rt_device_t</span> <span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_ASSERT</span><span class="p">(</span><span class="n">shell</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="nf">rt_device_read</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">rx_sem</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span> <span class="o">!=</span> <span class="n">device</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_POSIX_STDIO */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_DEVICE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">src</span><span class="err">\</span><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">RT_WEAK</span> <span class="kt">void</span> <span class="nf">rt_hw_console_output</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* empty console output */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">str</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="sc">&#39;\n&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SEGGER_RTT_printf</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s">&#34;%s&#34;</span><span class="p">,</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">RTM_EXPORT</span><span class="p">(</span><span class="n">rt_hw_console_output</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4实验效果">4、实验效果 +</h4><p>首先确保已经下载好<code>J-Link RTT Viewer</code>,直接去<a class="link" href="https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/" target="_blank" rel="noopener" +>官网</a>下载最新版本即可</p> +<p>然后编译和下载工程,注意下载方式为<code>J-Link</code></p> +<p>双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看<code>_SEGGER_RTT</code>变量地址(全局搜索即可,找到.bss._SEGGER_RTT)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/608cb3d791c683d7886a92eef5ae848f.png" +loading="lazy" +alt="image-20221003140449806" +></p> +<p>打开<code>J-Link RTT Viewer</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5e3d4a57e4a6b55dd62f61b5d6577105.png" +loading="lazy" +alt="image-20221003140736161" +></p> +<p>此时就可以正常使用segger_rtt了!</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/d09d8a0f28e2c45542199eb982dfed6e.png" +loading="lazy" +alt="image-20221003140911791" +></p>CPK-RA6M4智慧门禁系统教学https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/cover.jpg" alt="Featured image of post CPK-RA6M4智慧门禁系统教学" /><p><img src="https://img-blog.csdnimg.cn/img_convert/b98bb037592975e68632b30a8e0845f6.png" +loading="lazy" +alt="image-20220804171524901" +></p> +<h2 id="1项目介绍">1、项目介绍 +</h2><p>本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。</p> +<p>下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。</p> +<h2 id="2前期准备">2、前期准备 +</h2><p>开发工具:</p> +<ul> +<li>RT-Thread Studio</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a95d6ef5c3224144b554bcb416691bcf.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。</p> +<p>RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。</p> +<p>下载链接:<a class="link" href="https://www.rt-thread.org/page/download.html#studio" target="_blank" rel="noopener" +>RT-Thread Studio 下载</a></p> +<ul> +<li>瑞萨FSP(灵活配置软件包)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fbdf24dd4b66b39b2f108f558ecf4617.png" +loading="lazy" +alt="Flexible Software Package (FSP)" +></p> +<p>瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。</p> +<p>下载链接:<a class="link" href="https://github.com/renesas/fsp/releases/tag/v3.5.0" target="_blank" rel="noopener" +>瑞萨FSP v3.5.0</a></p> +<p>模块:</p> +<ul> +<li>AHT10</li> +<li>ESP8266</li> +<li>RC522及读卡标签</li> +<li>ssd1306 OLED显示屏</li> +</ul> +<h2 id="3模块介绍及使用">3、模块介绍及使用 +</h2><h4 id="31-aht10">3.1 AHT10 +</h4><h6 id="311底层i2c通信协议简介">3.1.1底层I2C通信协议简介 +</h6><p>I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。</p> +<p>而I2C通信的读写数据是通过等待从机的应答信号(ACK)。</p> +<p>也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。</p> +<p>这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。</p> +<p>当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。</p> +<p>简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。</p> +<h6 id="312-sensor框架的使用">3.1.2 sensor框架的使用 +</h6><p>在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。</p> +<p>掌握sensor框架的使用,需要了解一下API的调用:</p> +<table> +<thead> +<tr> +<th style="text-align:center"><strong>函数</strong></th> +<th style="text-align:center"><strong>描述</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">rt_device_find()</td> +<td style="text-align:center">根据传感器设备设备名称查找设备获取设备句柄</td> +</tr> +<tr> +<td style="text-align:center">rt_device_open()</td> +<td style="text-align:center">打开传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_read()</td> +<td style="text-align:center">读取数据</td> +</tr> +<tr> +<td style="text-align:center">rt_device_control()</td> +<td style="text-align:center">控制传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_set_rx_indicate()</td> +<td style="text-align:center">设置接收回调函数</td> +</tr> +<tr> +<td style="text-align:center">rt_device_close()</td> +<td style="text-align:center">关闭传感器设备</td> +</tr> +</tbody> +</table> +<h6 id="313-aht10对接到sensor框架">3.1.3 AHT10对接到sensor框架 +</h6><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">SCL</td> +<td style="text-align:center">P512</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P511</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动-&gt;Enable I2C BUS-&gt;使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f301db2fd8e1988f2ca4e311c5d973cf.png" +loading="lazy" +alt="image-20220805110607476" +></p> +<p>然后使用下面的程序完成模块初始化工作</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;sensor_asair_aht10.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define AHT10_I2C_BUS &#34;i2c1&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 模块初始化工作 */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_aht10_port</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_sensor_config</span> <span class="n">cfg</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">dev_name</span> <span class="o">=</span> <span class="n">AHT10_I2C_BUS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">user_data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">AHT10_I2C_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_init</span><span class="p">(</span><span class="s">&#34;aht10&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_ENV_EXPORT</span><span class="p">(</span><span class="n">rt_hw_aht10_port</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>AHT10温湿度数据读取</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="c1">// AHT10设备读取数值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">aht10_device_t</span> <span class="n">dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_port</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">dev</span> <span class="o">=</span> <span class="nf">aht10_init</span><span class="p">(</span><span class="n">AHT10_I2C_BUS</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes failure&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes ok!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read humidity 采集湿度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="nf">aht10_read_humidity</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read temperature 采集温度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="nf">aht10_read_temperature</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="32-esp8266">3.2 ESP8266 +</h4><h6 id="321-底层uart简介">3.2.1 底层uart简介 +</h6><p>UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。</p> +<p>UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。</p> +<ul> +<li>串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。</li> +<li>异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。</li> +<li>数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5fdffba894c94d48a14c4f64a9992b93.jpeg" +loading="lazy" +alt="查看源图像" +></p> +<p>空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。</p> +<p>起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。</p> +<p>数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。<code>先发送最低位,最后发送最高位</code>,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。</p> +<h6 id="322-mqtt通讯协议介绍">3.2.2 MQTT通讯协议介绍 +</h6><p>MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quot;轻量级&quot;通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。</p> +<p>其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。</p> +<p>实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。</p> +<p><img src="https://img-blog.csdnimg.cn/a665ee8ebb4d427bbfa4c8a7ec013913.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h6 id="323-at组件">3.2.3 AT组件 +</h6><p>AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/1eb3c2cd78584efa85656a2cdd8daa8f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。</p> +<h6 id="324-mqtt协议及at组件在rt-thread中的使用">3.2.4 MQTT协议及AT组件在RT-Thread中的使用 +</h6><p><strong>RT-Thread Settings设置</strong></p> +<p>添加AT Device及OneNET软件包</p> +<p>AT Device配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf1c743b728c70c2764a3db1d368039c.png" +loading="lazy" +alt="image-20220805122341394" +></p> +<p>OneNET配置:</p> +<p>首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b40025d68d9bd0f32ff6efa3b74ff12d.png" +loading="lazy" +alt="image-20220805122741348" +> +<img src="https://img-blog.csdnimg.cn/img_convert/c7c17c8d743dca043a098be627baf93c.png" +loading="lazy" +alt="image-20220805122836636" +></p> +<p>然后将创建的信息填写到settings中</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9588bef3c3bf99d27bdc3cbd56394ece.png" +loading="lazy" +alt="image-20220805123248475" +></p> +<p>在组件中使能AT命令</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ad6b80e0d34df83a213dcdbf85d4416b.png" +loading="lazy" +alt="image-20220805123407687" +></p> +<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">TX</td> +<td style="text-align:center">P100</td> +</tr> +<tr> +<td style="text-align:center">RX</td> +<td style="text-align:center">P101</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">5V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p><strong>FSP配置</strong></p> +<p>由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置</p> +<p>首先点击<code>RA Smart Configurator</code>,记住这里使用的FSP版本为<code>v3.5.0</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/7710c9a62ad3a4486362f9d4bf92869f.png" +loading="lazy" +alt="image-20220805152204348" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2cb89487678dcf16bf3c784851a42091.png" +loading="lazy" +alt="image-20220805153017364" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf0866f3d50eae91f43aee142ef06966.png" +loading="lazy" +alt="image-20220805153317144" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/58fb0f18f54f0eaf49598c6c20f67b62.png" +loading="lazy" +alt="image-20220805153416015" +></p> +<p>完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现<code>#include &lt;dfs_posix.h&gt;</code>未参与编译以及还有其他一些问题,可以参考这一issue<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6188" target="_blank" rel="noopener" +>[CPK-RA6M4] onenet上云报错&lt;RT-Thread 的版本为 4.1.0 及以上&gt;</a></p> +<p>现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。</p> +<p>然后就是数据上云,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;temperature&#34;</span><span class="p">,</span><span class="n">temperature</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_delay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;humidity&#34;</span><span class="p">,</span><span class="n">humidity</span> <span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/096cd5faec78062ac227adcc12f08f05.png" +loading="lazy" +alt="image-20220805145942277" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67bd30c613f9a819cc2b7abddb58a5bc.png" +loading="lazy" +alt="image-20220805145958887" +></p> +<h4 id="33-rc522">3.3 RC522 +</h4><h6 id="331-底层spi协议简介">3.3.1 底层SPI协议简介 +</h6><p>SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9d4277d0aba7be84c59b68efb9402995.png" +loading="lazy" +alt="SPI 主设备和从设备的连接方式" +></p> +<ul> +<li>MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。</li> +<li>MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。</li> +<li>SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。</li> +<li>CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。</li> +</ul> +<p>整体的传输大概可以分为以下几个过程:</p> +<p>(1)主机先将<code>NSS</code>信号拉低,这样保证开始接收数据;</p> +<p>(2)当<strong>接收端</strong>检测到时钟的边沿信号时,它将立即读取<strong>数据线</strong>上的信号,这样就得到了一位数据(1<code>bit</code>;由于时钟是随数据一起发送的,因此指定<strong>数据的传输速度并不重要</strong>,尽管设备将具有可以运行的最高速度。</p> +<p>(3)<strong>主机</strong>发送到<strong>从机</strong>时:主机产生相应的时钟信号,然后数据<strong>一位一位</strong>地将从<code>MOSI</code>信号线上进行发送到从机;</p> +<p>(4)<strong>主机</strong>接收<strong>从机</strong>数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过<code>MISO</code>信号线发送;</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/3c32f25bed1d6e44c840608e4e352fc4.png" +loading="lazy" +alt="查看源图像" +></p> +<h6 id="332-rc522读卡机制说明">3.3.2 RC522读卡机制说明 +</h6><p>首先来看下RC522与M1卡的通讯流程:</p> +<p><strong>寻卡-&gt;防止卡片冲撞-&gt;选卡-&gt;休眠-&gt;发送0x40(7bit)-&gt;发送0x43-&gt;发送0xa0等4字节-&gt;发送0x00等18字节</strong></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/4c59b975aa9fdccbb19b38b059b87e1a.png" +loading="lazy" +alt="image-20220805154320392" +></p> +<ul> +<li> +<p>复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。</p> +</li> +<li> +<p>防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。</p> +</li> +<li> +<p>选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。</p> +</li> +<li> +<p>三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。</p> +</li> +<li> +<p>对数据块的操作: +读(Read):读一个块的数据; +写(Write):在一个块中写数据; +加(Increment):对数据块中的数值进行加值; +减(Decrement):对数据块中的数值进行减值; +传输(Transfer):将数据寄存器中的内容写入数据块中; +中止(Halt):暂停卡片的工作;</p> +</li> +</ul> +<h6 id="333-rc522在rt-thread的使用">3.3.3 RC522在RT-Thread的使用 +</h6><p>首先打开settings,添加RC522软件包,并在硬件部分使能SPI1</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ef7c08d20f957c70b67fe63943fec730.png" +loading="lazy" +alt="image-20220805155052783" +></p> +<p>打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/263c237d561d232466249aacb0dd42a4.png" +loading="lazy" +alt="image-20220805155448374" +></p> +<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">MOSI</td> +<td style="text-align:center">P411</td> +</tr> +<tr> +<td style="text-align:center">MISO</td> +<td style="text-align:center">P410</td> +</tr> +<tr> +<td style="text-align:center">SCL</td> +<td style="text-align:center">P412</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P311</td> +</tr> +<tr> +<td style="text-align:center">RST</td> +<td style="text-align:center">P312</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +<tr> +<td style="text-align:center">IRQ</td> +<td style="text-align:center">悬空</td> +</tr> +</tbody> +</table> +<p>代码部分参考RC522sample</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/474416ef76e9523302b9cdd544bbf03b.png" +loading="lazy" +alt="image-20220805155715593" +></p> +<p>SPI初始化配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;mfrc522.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_spi_device</span> <span class="n">mfrc522_spi_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">pin</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> <span class="n">spi_cs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_spi_rc522_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_err_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Attach Device +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span> <span class="o">=</span> <span class="n">MFRC522_SS_PIN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span> <span class="o">=</span> <span class="nf">rt_spi_bus_attach_device</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">,</span> <span class="n">MFRC522_SPI_BUS_NAME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">spi_cs</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[RC522] Failed to attach device %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Set device SPI Mode +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="n">rt_spi_configuration</span> <span class="n">cfg</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">data_width</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">RT_SPI_MASTER</span> <span class="o">|</span> <span class="n">RT_SPI_MODE_0</span> <span class="o">|</span> <span class="n">RT_SPI_MSB</span> <span class="o">|</span> <span class="n">RT_SPI_NO_CS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">max_hz</span> <span class="o">=</span> <span class="n">MFRC522_SPICLOCK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_spi_configure</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 导出到自动初始化 */</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_hw_spi_rc522_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>另外需要在完成一下配置,<code>双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5045a3933b508b5267b5fb9eeec6064b.png" +loading="lazy" +alt="image-20220805155922942" +></p> +<p>打开mfrc522.c,修改配置<code>MFRC522_SS_PIN</code>及<code>MFRC522_RST_PIN</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c61dba211ccb8ece988de9e703dc15cb.png" +loading="lazy" +alt="image-20220805161330936" +></p> +<p>打开rtconfig.h,找到以下两个引脚的定义,修改成如下:</p> +<p>注意:<strong><code>一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置</code></strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define MFRC522_SS_PIN 0x3b +</span></span><span class="line"><span class="cl">#define MFRC522_RST_PIN 0x3c +</span></span></code></pre></td></tr></table> +</div> +</div><p>至此,RC522的相关配置结束</p> +<h4 id="34-ssd1306">3.4 SSD1306 +</h4><h6 id="341-底层i2c通信协议">3.4.1 底层I2C通信协议 +</h6><p>(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)</p> +<h6 id="342-ssd1306在rt-thred的使用">3.4.2 SSD1306在RT-Thred的使用 +</h6><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">SCL</td> +<td style="text-align:center">P400</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P401</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>RT-Thread Settings配置:</p> +<p>添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c6b56810a69b472ea12eaa4e8d60008a.png" +loading="lazy" +alt="image-20220805162320450" +></p> +<p>打开rtconfig.h,添加i2c代码,<code>注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SCL_PIN 0x400 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SDA_PIN 0x401 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开drv_soft_i2c.c文件,添加代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define I2C0_BUS_CONFIG \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> { \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .scl = BSP_I2C0_SCL_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .sda = BSP_I2C0_SDA_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .bus_name = &#34;i2c0&#34;, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> } +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/04a3d96e15bbde106c73e389eca7fe10.png" +loading="lazy" +alt="image-20220805162941069" +></p> +<p>生成配置之后添加用户代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;ssd1306.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">25</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Hello RT-Thread!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_APP_EXPORT</span><span class="p">(</span><span class="n">oled_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实时时钟显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Now Time&#34;</span><span class="p">,</span> <span class="n">Font_16x26</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">40</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;:&#34;</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>温湿度数据显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Humi_Temp_Detection!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Temperature: %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Temperature_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Humidity:%d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">47</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Humidity_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4整体代码框架">4、整体代码框架 +</h2><h4 id="41-多线程任务分配">4.1 多线程任务分配 +</h4><p>本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。</p> +<p>所以共创建四个线程:</p> +<p>(1)RC522_thread:用于RC522读卡</p> +<p>(2)aht10_read_thread:用于aht10读取温湿度数值</p> +<p>(3)onenet_aht10_thread:云端数据上报</p> +<p>(4)oled_thread:OLED显示</p> +<h4 id="42-线程间交互">4.2 线程间交互 +</h4><p>本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。</p> +<h4 id="43-代码整合">4.3 代码整合 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/8aed1d64ef9fd8e219744b794b8dd048.png" +loading="lazy" +alt="image-20220802210559475" +></p> +<p>在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。</p> +<p>都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/36369721fa7745022aab2ad2492dc64f.png" +loading="lazy" +alt="image-20220805171602257" +></p> +<h2 id="5踩坑指南">5、踩坑指南 +</h2><p>其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:</p> +<p>(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为<code>v3.5.0</code></p> +<p>(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。</p> +<p>(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。</p> +<div class="video-wrapper"> +<iframe src="https://player.bilibili.com/player.html?as_wide=1&amp;high_quality=1&amp;page=1.8&bvid=BV1Ld4y1N7eo" +scrolling="no" +frameborder="no" +framespacing="0" +allowfullscreen="true" +> +</iframe> +</div>ART-Pi 网络时钟https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/cover.jpg" alt="Featured image of post ART-Pi 网络时钟" /><h2 id="玩转rt-thread自制网络时钟">《玩转RT-Thread》自制网络时钟 +</h2><hr> +<p>@[toc]</p> +<h2 id="一准备工作">一、准备工作 +</h2><ul> +<li> +<p>开发平台:RT-Thread Studio</p> +</li> +<li> +<p>开发板:ART-PI</p> +</li> +<li> +<p>主控芯片:STM32H750</p> +</li> +<li> +<p>温湿度传感器:SHT30</p> +</li> +<li> +<p>显示模组:0.96’OLED(SSD1306)</p> +</li> +<li> +<p>串口调试助手:SecureCRT</p> +</li> +</ul> +<p>注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。</p> +<h2 id="二新建rt-thread-项目">二、新建RT-Thread 项目 +</h2><p><img src="https://img-blog.csdnimg.cn/dfeff108ee0241919514065992e79ef8.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/9f49c13343914adf8d92f12a1ebf832e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="三获取温湿度数据">三、获取温湿度数据 +</h2><h4 id="1双击打开左边导航栏的rt-thread-setting">1、双击打开左边导航栏的RT-Thread Setting +</h4><p><img src="https://img-blog.csdnimg.cn/096e053c2ec545a9950c86dcb1e12d9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2使能软件模拟i2c单击点亮即可">2、使能软件模拟i2c(单击点亮即可) +</h4><p><img src="https://img-blog.csdnimg.cn/6bb6a362155641c0b0b6fa0953c60e45.png" +loading="lazy" +></p> +<h4 id="3配置i2c及相关引脚">3、配置i2c及相关引脚 +</h4><p><code>这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置</code></p> +<p><img src="https://img-blog.csdnimg.cn/ae8aaaa39cf04296809e01ccef73d980.png" +loading="lazy" +></p> +<h4 id="4添加sht3x软件包">4、添加SHT3X软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/d480f380b622466c9c38ae5129550067.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置,点击编译并下载</code></p> +<p>具体RT-Thread Studio的一般使用可参照<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124079730?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)</a></p> +<p><code>此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功</code></p> +<p><img src="https://img-blog.csdnimg.cn/04803141590e474bbe767242a8258ed5.png" +loading="lazy" +></p> +<p>此时在串口输入help,可以看出有一个sht3x配置</p> +<p><img src="https://img-blog.csdnimg.cn/bb9d35af5d19463282a1bd8400e90364.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入: +</span></span><span class="line"><span class="cl">sht3x probe i2c3 pd +</span></span><span class="line"><span class="cl">sht3x read(读取温湿度信息) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="四获取ntp时间">四、获取NTP时间 +</h2><h4 id="1使能选择wifi框架">1、使能选择WiFi框架 +</h4><p><img src="https://img-blog.csdnimg.cn/fac0022dff324acc9aa4a94e85407e69.png" +loading="lazy" +></p> +<h4 id="2使能ap6212库">2、使能AP6212库 +</h4><p><img src="https://img-blog.csdnimg.cn/97afeb11678140b2a5acbea44bc8937f.png" +loading="lazy" +></p> +<h4 id="3添加easyflash和netutils软件包">3、添加easyflash和netutils软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/08cda56d446541358d2b5038545ca284.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>鼠标右键netutils打开配置项</code></p> +<p><img src="https://img-blog.csdnimg.cn/cd98d8f9bb0f4f15941c4617c32b7aa3.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>使能NTP (网络时间协议)客户端 </code></p> +<p><img src="https://img-blog.csdnimg.cn/7fe0c1a627d94d1dba87dbcf4918d127.png" +loading="lazy" +></p> +<p><code>使能软件模拟RTC</code></p> +<p><img src="https://img-blog.csdnimg.cn/f2ac26826c0a463bb1124804fcc7c563.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置</code></p> +<p><code>修改配置</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cassandra" data-lang="cassandra"><span class="line"><span class="cl"><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="err">打开电脑中项目所在的路径</span><span class="o">-</span><span class="n">workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">packages</span><span class="o">-</span><span class="n">EasyFlash</span><span class="o">-</span><span class="n">v4</span><span class="err">.1.0</span><span class="o">-</span><span class="n">port</span><span class="err">,将</span><span class="n">port目录下的ef_fal_port</span><span class="p">.</span><span class="n">c文件复制到workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">board</span><span class="o">-</span><span class="n">port中</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="err">修改</span><span class="n">port中宏定义FAL_EF_PART_NAME</span><span class="w"> </span><span class="err">中的名字</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">#</span><span class="n">define</span><span class="w"> </span><span class="n">FAL_EF_PART_NAME</span><span class="w"> </span><span class="s">&#34;easyflash&#34;</span><span class="w"> </span><span class="c1">//修改后的宏定义 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>此时再编译并下载到开发板中</code></p> +<h4 id="4连接wifi">4、连接WiFi +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">wifi</span> <span class="n">scan</span> <span class="c1">//搜索wifi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">wifi</span> <span class="n">join</span> <span class="p">[</span><span class="n">SSID</span><span class="p">]</span> <span class="p">[</span><span class="n">PASSWORD</span><span class="p">]</span> <span class="c1">//连接WiFi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="nl">SSID</span><span class="p">:</span><span class="n">WiFi名称</span> +</span></span><span class="line"><span class="cl"><span class="n">PASSWORD</span><span class="err">:</span><span class="n">WiFi密码</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5设置开机自连接wifi">5、设置开机自连接WiFi +</h4><p><code>(1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_WIFI +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_mgnt.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_cfg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_prot.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;easyflash.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;fal.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#if (EF_SW_VERSION_NUM &lt; 0x40000) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">base64_table</span><span class="p">[</span><span class="mi">65</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="mi">256</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3E</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3F</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x34</span><span class="p">,</span> <span class="mh">0x35</span><span class="p">,</span> <span class="mh">0x36</span><span class="p">,</span> <span class="mh">0x37</span><span class="p">,</span> <span class="mh">0x38</span><span class="p">,</span> <span class="mh">0x39</span><span class="p">,</span> <span class="mh">0x3A</span><span class="p">,</span> <span class="mh">0x3B</span><span class="p">,</span> <span class="mh">0x3C</span><span class="p">,</span> <span class="mh">0x3D</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0A</span><span class="p">,</span> <span class="mh">0x0B</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x0D</span><span class="p">,</span> <span class="mh">0x0E</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x10</span><span class="p">,</span> <span class="mh">0x11</span><span class="p">,</span> <span class="mh">0x12</span><span class="p">,</span> <span class="mh">0x13</span><span class="p">,</span> <span class="mh">0x14</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x16</span><span class="p">,</span> <span class="mh">0x17</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="mh">0x19</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0x1B</span><span class="p">,</span> <span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x1D</span><span class="p">,</span> <span class="mh">0x1E</span><span class="p">,</span> <span class="mh">0x1F</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="mh">0x21</span><span class="p">,</span> <span class="mh">0x22</span><span class="p">,</span> <span class="mh">0x23</span><span class="p">,</span> <span class="mh">0x24</span><span class="p">,</span> <span class="mh">0x25</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0x27</span><span class="p">,</span> <span class="mh">0x28</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x29</span><span class="p">,</span> <span class="mh">0x2A</span><span class="p">,</span> <span class="mh">0x2B</span><span class="p">,</span> <span class="mh">0x2C</span><span class="p">,</span> <span class="mh">0x2D</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x2F</span><span class="p">,</span> <span class="mh">0x30</span><span class="p">,</span> <span class="mh">0x31</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0x33</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pos</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">end</span><span class="p">,</span> <span class="o">*</span><span class="n">in</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">olen</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">=</span> <span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="cm">/* 3-byte blocks to 4-byte */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">+=</span> <span class="n">olen</span> <span class="o">/</span> <span class="mi">72</span><span class="p">;</span> <span class="cm">/* line feeds */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span><span class="o">++</span><span class="p">;</span> <span class="cm">/* nul termination */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">end</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span> <span class="o">+</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pos</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">6</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x3f</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * return: length, 0 is error. +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">input_length</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">out_len</span> <span class="o">=</span> <span class="n">input_length</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">input_length</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_a</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_b</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_c</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_d</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">triple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sextet_a</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_b</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_c</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_d</span> <span class="o">&lt;&lt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">6</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_info</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">,</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">),</span> <span class="n">buff</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_len</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">wlan_cfg_len</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">base64_buf</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">base64_buf</span> <span class="o">=</span> <span class="nf">rt_malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span> <span class="cm">/* 3-byte blocks to 4-byte, and the end. */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">base64_buf</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* (EF_SW_VERSION_NUM &lt; 0x40000) */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">rt_wlan_cfg_ops</span> <span class="n">ops</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_cfg</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">get_len</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_cfg</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">easyflash_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_set_ops</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ops</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_cache_refresh</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在main.c中添加自动连接函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define LED_PIN GET_PIN(I, 8) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* init Wi-Fi auto connect feature */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* enable auto reconnect on WLAN device */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。</code></p> +<h2 id="五oled屏显示温湿度和实时时间信息">五、OLED屏显示温湿度和实时时间信息 +</h2><h4 id="1添加u8g2软件包">1、添加u8g2软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/9aa5ecc3b3484b14b1c57ef4c75aae73.png" +loading="lazy" +></p> +<h4 id="2编写oled_display显示线程">2、编写oled_display显示线程 +</h4><p><code>(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。</code></p> +<p><code>代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rthw.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;U8g2lib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;drv_soft_i2c.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sht3x.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">sht3x_device_t</span> <span class="nf">sht3x_init</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">i2c_bus_name</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">sht3x_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="nf">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device_t</span> <span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define OLED_I2C_PIN_SCL 24 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define OLED_I2C_PIN_SDA 25 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">U8G2_SSD1306_128X64_NONAME_F_SW_I2C</span> <span class="nf">u8g2</span><span class="p">(</span><span class="n">U8G2_R0</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* clock=*/</span> <span class="n">OLED_I2C_PIN_SCL</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* data=*/</span> <span class="n">OLED_I2C_PIN_SDA</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* reset=*/</span> <span class="n">U8X8_PIN_NONE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define SUN 0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SUN_CLOUD 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define CLOUD 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RAIN 3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define THUNDER 4 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeatherSymbol</span><span class="p">(</span><span class="n">u8g2_uint_t</span> <span class="n">x</span><span class="p">,</span> <span class="n">u8g2_uint_t</span> <span class="n">y</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// fonts used: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_embedded_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_weather_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">69</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN_CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">65</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">64</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">RAIN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">THUNDER</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_embedded_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeather</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">degree</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">degree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawHumidity</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">humidity</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;%&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">48</span><span class="o">+</span><span class="mi">3</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;Hi~&#34;</span><span class="p">);</span> <span class="c1">// requires enableUTF8Print() +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_6x13_tr</span><span class="p">);</span> <span class="c1">// choose a suitable font +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s">&#34;By Mculover666&#34;</span><span class="p">);</span> <span class="c1">// write something to the internal memory +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device_t</span> <span class="n">sht3x_device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device</span> <span class="o">=</span> <span class="n">sht3x_init</span><span class="p">(</span><span class="s">&#34;i2c3&#34;</span><span class="p">,</span> <span class="mh">0x44</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">mstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">hstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">time_t</span> <span class="n">now</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="nc">tm</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">min</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">hour</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">0</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">(</span><span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">=</span><span class="n">gmtime</span><span class="p">((</span><span class="k">const</span> <span class="n">time_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">now</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">hour</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_hour</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">min</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_min</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">min</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">hour</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">firstPage</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">do</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso42_tn</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">hstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="s">&#34;:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">67</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">mstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span> <span class="n">u8g2</span><span class="p">.</span><span class="n">nextPage</span><span class="p">()</span> <span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">1</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeather</span><span class="p">(</span><span class="n">SUN</span><span class="p">,</span> <span class="n">temperature</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">2</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">humidity</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawHumidity</span><span class="p">(</span><span class="n">RAIN</span><span class="p">,</span> <span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">oled_display</span><span class="p">,</span> <span class="n">oled</span> <span class="n">start</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在 applications 文件夹下创建oled_display.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* APPLICATIONS_OLED_DISPLAY_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(3)最终的主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2020, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2020-09-02 RT-Thread first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">oled_display</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/*-------------------------- I2C CONFIG BEGIN --------------------------*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C1_SCL_PIN 24 </span><span class="c1">// p2 10 PB8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C1_SDA_PIN 25 </span><span class="c1">// p2 7 PB9 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C3_SCL_PIN 119 </span><span class="c1">//p1 29 PH7 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C3_SDA_PIN 120 </span><span class="c1">//p1 28 PH8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/*-------------------------- UART CONFIG END --------------------------*/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六实验展示">六、实验展示 +</h2><p><img src="https://img-blog.csdnimg.cn/c0cbf5357ce14d7d963684d4338eee9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/d329c18ee11d45a59252f42bb043663b.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/99f00b0cf72b4e20a0697914e7048f97.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="七问题总结">七、问题总结 +</h2><p><code>注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// cpp函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。</code></p> +<hr> +<p>这次的分享就到这里,有相关问题的欢迎留言私信!</p>线程间同步 信号量https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/Sun, 17 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/cover.jpg" alt="Featured image of post 线程间同步 信号量" /><h2 id="一概述">一、概述: +</h2><blockquote> +<p>多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:</p> +</blockquote> +<p><strong>信号量</strong>(semaphore)、<strong>互斥量</strong>(mutex)、和<strong>事件集</strong>(event)</p> +<h2 id="二信号量">二、信号量 +</h2><h4 id="1简述">1、简述 +</h4><p>信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到<code>同步</code>或<code>互斥</code>的目的。</p> +<p>信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当<code>信号量实例数目为零时</code>,再申请该信号量的线程就会被<code>挂起</code>在该信号量的等待队列上,等待可用的信号量实例(资源)。</p> +<p><img src="https://img-blog.csdnimg.cn/55d38f32e6e84b038d35a27bea1b9074.png" +loading="lazy" +></p> +<h4 id="2信号量结构体">2、信号量结构体 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_ipc_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; 继承自ipc_object类 */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">value</span><span class="p">;</span> <span class="cm">/**&lt; value of semaphore. */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">reserved</span><span class="p">;</span> <span class="cm">/**&lt; reserved field 预留*/</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。</p> +<h4 id="3信号量使用及管理">3、信号量使用及管理 +</h4><blockquote> +<p>对一个信号量的操作包含:<code>创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量</code>。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d8bde585ecaa4669817d29f0ffdc34f5.png" +loading="lazy" +></p> +<p>1)动态创建信号量</p> +<blockquote> +<p>当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。</p> +</blockquote> +<blockquote> +<p>当选择 <code>RT_IPC_FLAG_FIFO(先进先出)</code>方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; +当选择 <code>RT_IPC_FLAG_PRIO(优先级等待)</code>方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。</p> +</blockquote> +<p><code>函数声明</code>:</p> +<p><code>rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);</code></p> +<p><code>参数介绍</code>:</p> +<p><img src="https://img-blog.csdnimg.cn/f829de152967470393d8b7605e4c2b12.png" +loading="lazy" +></p> +<p><code>注意:</code></p> +<p><code>(1)此处的*name定义最多只能显示八个字符</code></p> +<p><code>(2)查看rt_sem_create()函数返回值是--&gt;typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore </code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// flag值 如下 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_FIFO 0x00 </span><span class="cm">/**&lt; FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_PRIO 0x01 </span><span class="cm">/**&lt; PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>2)动态创建的信号量删除</p> +<blockquote> +<p>系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。</p> +</blockquote> +<blockquote> +<p>调用这个函数时,系统将删除这个信号量。<code>如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。</code></p> +</blockquote> +<p><code>函数声明</code> +<code>rt_err_t rt_sem_delete(rt_sem_t sem);</code></p> +<p><code>实例</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)静态创建信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">value</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<p><img src="https://img-blog.csdnimg.cn/cbe2c704ffc849cf8859a6c46237681a.png" +loading="lazy" +></p> +<p>4)脱离信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于<code>静态初始化的信号量</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_detach</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>5)获取信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。</p> +<p>如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择<code>直接返回、或挂起等待一段时间、或永久等待</code>,直到其他线程或中断释放该信号量。</p> +<p>如果在参数 time 指定的时间内依然得不到信号量,线程将<code>超时返回</code>,返回值是<code> - RT_ETIMEOUT</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_take</span> <span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> <span class="kt">rt_int32_t</span> <span class="n">time</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// time参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_FOREVER -1 </span><span class="cm">/**&lt; Block forever until get resource. */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_NO 0 </span><span class="cm">/**&lt; Non-block. */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 扩展: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_trytake</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> <span class="c1">// 无等待获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>6)信号量释放</p> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>描述</code></p> +<blockquote> +<p>例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。</p> +</blockquote> +<h4 id="4信号量实例演示">4、信号量实例演示 +</h4><blockquote> +<p>这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/632591398002468c9a69cf3e4ac8cfe4.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/4293c61a10d14a128312fd50d7d2c9c6.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>查看信号量设定的标志位是<code>RT_IPC_FLAG_FIFO</code>,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1-&gt;线程2-&gt;线程1-&gt;线程2&hellip;的顺序执行的,这样就实现了线程的并发互斥运行。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1000730483a345728f1faa2ba68bde2d.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/31c3f295be2e41f9ab8d674ade353007.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>最后附上测试源代码</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> <span class="n">sem2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1</span><span class="p">,</span><span class="n">th2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th1_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">8000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="n">sem1</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">100</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th1_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="n">sem1</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="s">&#34;sem2&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_init successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th1</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th1&#34;</span><span class="p">,</span> <span class="n">th1_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th2</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th2&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th2</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>线程管理https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 线程管理" /><p>原理实战请查看<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124539095" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)</a></p> +<h1 id="一序言">一、序言 +</h1><p>在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 +同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。</p> +<p>下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:</p> +<blockquote> +<p>1.读取数据 +2.显示数据</p> +</blockquote> +<p>简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 +<img src="https://img-blog.csdnimg.cn/6d57696f2ffc4e859bf8c8c1ffc0789e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +在RT-Thread 中,与上述子任务对应的程序实体就是线程,<code>线程是实现任务的载体</code>。 +它是RT-Thread中<code>最基本的调度单位</code>,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的<code>优先级</code>,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 +<code>上下文:</code>当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。</p> +<h1 id="二线程管理的功能特点">二、线程管理的功能特点 +</h1><p>RT-Thread 线程管理的主要功能是<code>对线程进行管理和调度</code>,系统中总共存在两类线程,分别是<code>系统线程</code>和<code>用户线程</code>。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。</p> +<p>如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 +<img src="https://img-blog.csdnimg.cn/5584a47897de430597897d3a6bddd710.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>RT-Thread 的线程调度器是<code>抢占式</code>的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。</li> +<li>当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。</li> +<li>当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(<code>详细内容可参考</code><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124145153" target="_blank" rel="noopener" +>【操作系统】进程上下文和线程上下文</a>)信息恢复。</li> +</ul> +<h1 id="三线程的工作机制">三、线程的工作机制 +</h1><h2 id="1线程控制块">1.线程控制块 +</h2><p>在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* 线程控制块*/ +</span></span><span class="line"><span class="cl">struct rt_thread +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* rt 对象*/ +</span></span><span class="line"><span class="cl"> char name[RT_NAME_MAX]; /* 线程名称*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t type; /* 对象类型*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t flags; /* 标志位*/ +</span></span><span class="line"><span class="cl"> rt_list_t list; /* 对象列表*/ +</span></span><span class="line"><span class="cl"> rt_list_t tlist; /* 线程列表*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 栈指针与入口指针*/ +</span></span><span class="line"><span class="cl"> void *sp; /* 栈指针*/ +</span></span><span class="line"><span class="cl"> void *entry; /* 入口函数指针*/ +</span></span><span class="line"><span class="cl"> void *parameter; /* 参数*/ +</span></span><span class="line"><span class="cl"> void *stack_addr; /* 栈地址指针*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t stack_size; /* 栈大小*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 错误代码*/ +</span></span><span class="line"><span class="cl"> rt_err_t error; /* 线程错误代码*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t stat; /* 线程状态*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t current_priority; /* 当前优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t init_priority; /* 初始优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t number_mask; +</span></span><span class="line"><span class="cl"> ...... +</span></span><span class="line"><span class="cl"> rt_ubase_t init_tick; /* 线程初始化计数值*/ +</span></span><span class="line"><span class="cl"> rt_ubase_t remaining_tick; /* 线程剩余计数值*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> struct rt_timer thread_timer; /* 内置线程定时器*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t user_data; /* 用户数据*/ +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code> 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。</code></li> +<li><code>cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。</code></li> +<li><code>最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。</code></li> +</ul> +<h2 id="2线程的重要属性">2.线程的重要属性 +</h2><h4 id="1-线程栈">(1) 线程栈 +</h4><ul> +<li>RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。</li> +<li>线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。</li> +<li>对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。</li> +<li>线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 +<img src="https://img-blog.csdnimg.cn/041732b5e1fd43d5a62382931ad50360.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></li> +</ul> +<h4 id="2-线程状态">(2) 线程状态 +</h4><p>线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 +在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:</p> +<table> +<thead> +<tr> +<th>状态</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>初始态</td> +<td>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</td> +</tr> +<tr> +<td>就绪态</td> +<td>在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY</td> +</tr> +<tr> +<td>运行态</td> +<td>线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING</td> +</tr> +<tr> +<td>挂起态</td> +<td>也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND</td> +</tr> +<tr> +<td>关闭态</td> +<td>当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE</td> +</tr> +</tbody> +</table> +<h4 id="3-线程优先级">(3) 线程优先级 +</h4><ul> +<li> +<p>RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。</p> +</li> +<li> +<p>RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。</p> +</li> +</ul> +<h4 id="4-时间片">(4) 时间片 +</h4><blockquote> +<p>每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。</p> +</blockquote> +<p>假设有2 个<code>优先级相同的就绪态线程A 与B</code>,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 +<img src="https://img-blog.csdnimg.cn/31c4fb41bf8947c1a47864b12b9e602e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5-线程的入口函数">(5) 线程的入口函数 +</h4><p>线程控制块中的<code>entry</code>是线程的入口函数,它是线程实现预期功能的函数。</p> +<p>线程的入口函数由用户设计实现,一般有以下两种代码形式: +1.<code>无限循环模式</code></p> +<blockquote> +<p>在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 +界事件的发生,而后进行相应的服务:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void thread_entry(void* paramenter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">while (1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> /* 等待事件的发生*/ +</span></span><span class="line"><span class="cl"> /* 对事件进行服务、进行处理*/ +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 +所以在实时操作系统中必须注意的一点就是:<!-- raw HTML omitted -->线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。<!-- raw HTML omitted --></p> +</blockquote> +<p>2.<code>顺序执行或有限次循环模式</code></p> +<blockquote> +<p>如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">static void thread_entry(void* parameter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* 处理事务#1 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#2 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#3 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6-常见的线程错误码">(6) 常见的线程错误码 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_EOK 0 /* 无错误*/ +</span></span><span class="line"><span class="cl">#define RT_ERROR 1 /* 普通错误*/ +</span></span><span class="line"><span class="cl">#define RT_ETIMEOUT 2 /* 超时错误*/ +</span></span><span class="line"><span class="cl">#define RT_EFULL 3 /* 资源已满*/ +</span></span><span class="line"><span class="cl">#define RT_EEMPTY 4 /* 无资源*/ +</span></span><span class="line"><span class="cl">#define RT_ENOMEM 5 /* 无内存*/ +</span></span><span class="line"><span class="cl">#define RT_ENOSYS 6 /* 系统不支持*/ +</span></span><span class="line"><span class="cl">#define RT_EBUSY 7 /* 系统忙*/ +</span></span><span class="line"><span class="cl">#define RT_EIO 8 /* IO 错误*/ +</span></span><span class="line"><span class="cl">#define RT_EINTR 9 /* 中断系统调用*/ +</span></span><span class="line"><span class="cl">#define RT_EINVAL 10 /* 非法参数*/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3线程状态切换">3.线程状态切换 +</h2><p>RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: +<img src="https://img-blog.csdnimg.cn/3c79cc6198144f02b4830d4521384c30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<ul> +<li>线程通过调用函数<code>rt_thread_create/init()</code> 进入到初始状态<code>(RT_THREAD_INIT)</code>;</li> +<li>初始状态的线程通过调用函数<code>rt_thread_startup()</code> 进入到就绪状态<code>(RT_THREAD_READY)</code>;</li> +<li>就绪状态的线程被调度器调度后进入运行状态<code>(RT_THREAD_RUNNING)</code>;</li> +<li>当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态<code>(RT_THREAD_SUSPEND)</code>;</li> +</ul> +</blockquote> +<blockquote> +<ul> +<li>处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。</li> +<li>挂起状态的线程,如果调用<code>rt_thread_delete/detach() </code>函数,将更改为关闭状态<code>(RT_THREAD_CLOSE)</code>;</li> +<li>而运行状态的线程,如果运行结束,就会在线程的最后部分执行<code>rt_thread_exit() </code>函数,将状态更改为关闭状态。</li> +</ul> +</blockquote> +<p><!-- raw HTML omitted --><code>!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。</code></p> +<h2 id="4系统线程">4.系统线程 +</h2><p>系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。</p> +<h4 id="1空闲线程">(1)空闲线程 +</h4><p><code>空闲线程</code>是系统创建的最低优先级的线程,线程状态<code>永远为就绪态</code>。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。</p> +<p>另外,空闲线程在RT-Thread 也有着它的特殊用途:</p> +<ul> +<li>若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。</li> +<li>空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>钩子函数</a>和<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5ev7%5earticle_score_rank,157%5ev4%5econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>看门狗</a>不懂的可以看这里)</li> +</ul> +<h4 id="2-主线程">(2) 主线程 +</h4><p>在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。</p> +<p>过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 +<img src="https://img-blog.csdnimg.cn/b08911ca57334476945d473ab814f006.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="四线程的管理方式">四、线程的管理方式 +</h1><p>可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。</p> +<p>动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。</p> +<p>下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 +<img src="https://img-blog.csdnimg.cn/fea91f8134b648ccaefeb5cf201de15f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="1创建和删除线程">1.创建和删除线程 +</h2><h4 id="1创建线程">(1)创建线程 +</h4><p>一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_thread_t</span> <span class="n">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。</p> +</blockquote> +<p>线程创建rt_thread_create() 的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/f1ba4c76de384fcc91060025bff4bef7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2删除线程">(2)删除线程 +</h4><p>对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:</p> +<pre><code>rt_err_t rt_thread_delete(rt_thread_t thread); +</code></pre> +<p>调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。</p> +<p>线程删除rt_thread_delete() 接口的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/eb9a07efdd95454c8873506f5178d1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。</code></p> +<h2 id="2初始化和脱离线程">2.初始化和脱离线程 +</h2><h4 id="1初始化线程">(1)初始化线程 +</h4><p><code>线程的初始化</code>可以使用下面的函数接口完成,来初始化静态线程对象:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="n">rt_thread_init</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="n">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/c1e6ca6ef6b84ebe93d0888ff71332af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2脱离线程">(2)脱离线程 +</h4><p>对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:</p> +<pre><code>rt_err_t rt_thread_detach (rt_thread_t thread); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>thread</td> +<td>线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT_EOK</td> +<td>线程脱离成功</td> +</tr> +<tr> +<td>-RT_ERROR</td> +<td>线程脱离失败</td> +</tr> +</tbody> +</table> +<h2 id="3启动线程">3.启动线程 +</h2><p>创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:</p> +<pre><code>rt_err_t rt_thread_startup(rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/431f38ae0feb46dc833f9835ec57577e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 +动的线程优先级比当前线程优先级高,将立刻切换到这个线程。</p> +</blockquote> +<h2 id="4获得当前线程">4.获得当前线程 +</h2><p>在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:</p> +<pre><code>rt_thread_t rt_thread_self(void); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/33c1e79ddc8b42c0a28237a91e67b92c.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="5使线程出让处理器资源">5.使线程出让处理器资源 +</h2><blockquote> +<p>当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。</p> +</blockquote> +<p>线程让出处理器使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_yield(void); +</code></pre> +<blockquote> +<p>调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。</p> +</blockquote> +<h2 id="6使线程睡眠">6.使线程睡眠 +</h2><blockquote> +<p>在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。</p> +</blockquote> +<p>线程睡眠可使用以下三个函数接口:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_thread_sleep(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_delay(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_mdelay(rt_int32_t ms); +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/6ebefaeea61f48a7b26d43e0d6589055.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="7挂起和恢复线程">7.挂起和恢复线程 +</h2><h4 id="1线程挂起">(1)线程挂起 +</h4><blockquote> +<ul> +<li>当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。</li> +<li>处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。</li> +</ul> +</blockquote> +<p><code>线程挂起</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_suspend (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/eed2dcfd794040798637c029b253fb87.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。</code></p> +<h4 id="2恢复线程">(2)恢复线程 +</h4><blockquote> +<p>恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 +所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。</p> +</blockquote> +<p><code>线程恢复</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_resume (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/0640fc789a1645d3b424f605d3aca937.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="8控制线程">8.控制线程 +</h2><p>当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:</p> +<pre><code>rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/348eb561864549528d9695d8f504af92.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<pre><code>指示控制命令cmd 当前支持的命令包括: +•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级; +•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用; +•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。 +</code></pre> +<h2 id="设置和删除空闲钩子">设置和删除空闲钩子 +</h2><blockquote> +<p>空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。</p> +</blockquote> +<p>设置/ 删除空闲钩子的接口如下:</p> +<pre><code>rt_err_t rt_thread_idle_sethook(void (*hook)(void)); +rt_err_t rt_thread_idle_delhook(void (*hook)(void)); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>设置/删除的钩子函数</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT-EOK</td> +<td>设置/删除成功</td> +</tr> +<tr> +<td>-RT_EFULL</td> +<td>设置失败</td> +</tr> +<tr> +<td>-RT_ENOSYS</td> +<td>删除失败</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。</code></p> +<h2 id="10设置调度器钩子">10.设置调度器钩子 +</h2><p><code>在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。</code></p> +<p>在系统线程切换时,这个钩子函数将被调用:</p> +<pre><code>void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); +</code></pre> +<p><code>设置调度器钩子函数的输入参数</code>如下表所示:</p> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>表示用户定义的钩子函数指针</td> +</tr> +</tbody> +</table> +<p><code>钩子函数hook() 的声明</code>如下:</p> +<pre><code>void hook(struct rt_thread* from, struct rt_thread* to); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>from</td> +<td>表示系统所要切换出的线程控制块指针</td> +</tr> +<tr> +<td>to</td> +<td>表示系统所要切换到的线程控制块指针</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。</code></p> +<hr> +<p>资料参考: +(1)<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5Ev7%5Earticle_score_rank,157%5Ev4%5Econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>【STM32】HAL库 STM32CubeMX教程五&mdash;-看门狗(独立看门狗,窗口看门狗)</a> +(2)<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>什么是钩子函数</a> +(3)<a class="link" href="https://www.rt-thread.org/document/site/#/" target="_blank" rel="noopener" +>RT-Thread文档中心</a></p>I2C(内核学习)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post I2C(内核学习)" /><h2 id="一i2c协议">一、i2c协议 +</h2><p>由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。</p> +<h2 id="二i2c物理层">二、i2c物理层 +</h2><ul> +<li> +<p>i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 +<code>SDA</code>:用于传输数据 +<code>SCL</code>:用于同步数据收发</p> +</li> +<li> +<p>每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问</p> +</li> +<li> +<p>i2c支持多主控,任何时间点都只能有一个主控。 +<img src="https://img-blog.csdnimg.cn/01cc1805f0db4842a836a7dae9b11978.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +</li> +<li> +<p>i2c器件的SDA引脚和SCL引脚是开漏电路<a class="link" href="https://blog.csdn.net/ngulb/article/details/81174233?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E5%BC%80%E6%BC%8F%E7%94%B5%E8%B7%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81174233.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>形式,因此,SDA和SCL总线都需要连接上拉电阻<a class="link" href="https://blog.csdn.net/fymx203/article/details/89426403?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164973690016782092947037%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164973690016782092947037&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-89426403.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E4%B8%8A%E6%8B%89%E7%94%B5%E9%98%BB&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>,当总线空闲时,两条总线均为高电平。</p> +</li> +<li> +<p>各器件的SDA和SCL信号线在总线上都是<code>线与</code>关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)</p> +</li> +</ul> +<h2 id="三i2c协议层">三、i2c协议层 +</h2><p>协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。</p> +<h4 id="1i2c总线的位传输">1.i2c总线的位传输 +</h4><p>数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 +数据改变:当SCL为低电平时,SDA才可以改变电平 +<code>i2c位传输时序图</code> +<img src="https://img-blog.csdnimg.cn/3bcc9522f82841b5a9808703e4c29fa9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2i2c总线的开始和结束信号">2.i2c总线的开始和结束信号 +</h4><p><code>开始信号</code>:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 +<code>结束信号</code>:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。</p> +<h4 id="3i2c应答信号">3.i2c应答信号 +</h4><ul> +<li>在<code>主机</code>发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答<code>ACK</code>(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)</li> +<li>当<code>从机</code>接收不到数据或通信故障时,<code>从机</code>必须使SDA保持高电平,<code>主机</code>产生一个结束信号终止传输或者产生新的传输。</li> +</ul> +<h4 id="4i2c总线的仲裁机制">4.i2c总线的仲裁机制 +</h4><ul> +<li>SDA的仲裁也是建立在总线具有<code>线与</code>逻辑功能的原理上的。</li> +<li>节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。</li> +<li>SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)</li> +<li>当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是<code>线与</code>连接。</li> +</ul> +<h2 id="四访问i2c总线设备">四、访问i2c总线设备 +</h2><p>一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:</p> +<table> +<thead> +<tr> +<th>函数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>rt_device_find()</td> +<td>根据I2C 总线设备名称查找设备获取设备<a class="link" href="https://blog.csdn.net/wyx0224/article/details/83385168?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164976053816780265492902%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164976053816780265492902&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-83385168.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E5%8F%A5%E6%9F%84&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>句柄</a></td> +</tr> +<tr> +<td>rt_i2c_transfer()</td> +<td>传输数据</td> +</tr> +</tbody> +</table> +<h2 id="五查找i2c总线设备">五、查找i2c总线设备 +</h2><p>在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,</p> +<pre><code>rt_device_t rt_device_find(const char* name); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td>i2c总线设备名称</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>&ndash;</td> +</tr> +<tr> +<td>设备句柄</td> +<td>查找到对应设备将返回相应的设备句柄</td> +</tr> +<tr> +<td>RT-NULL</td> +<td>没有找到相应的设备对象</td> +</tr> +</tbody> +</table> +<p>一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六数据传输">六、数据传输 +</h2><p>获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs[], +</span></span><span class="line"><span class="cl"> rt_uint32_t num); +</span></span></code></pre></td></tr></table> +</div> +</div><table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>bus</td> +<td>i2c总线设备句柄</td> +</tr> +<tr> +<td>msgs[]</td> +<td>待传输的消息数组指针</td> +</tr> +<tr> +<td>num</td> +<td>消息数组的元素个数</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>-</td> +</tr> +<tr> +<td>-</td> +<td>-</td> +</tr> +<tr> +<td>消息数组的元素个数</td> +<td>成功</td> +</tr> +<tr> +<td>错误码</td> +<td>失败</td> +</tr> +</tbody> +</table> +<ul> +<li>和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。</li> +<li>参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 +<code>!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。</code></li> +</ul> +<blockquote> +<p>I2C 消息数据结构原型如下:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct rt_i2c_msg +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">rt_uint16_t addr; /* 从机地址*/ +</span></span><span class="line"><span class="cl">rt_uint16_t flags; /* 读、写标志等*/ +</span></span><span class="line"><span class="cl">rt_uint16_t len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl">rt_uint8_t *buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。</li> +<li>标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 +<code>!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_I2C_WR 0x0000 /* 写标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_RD (1u &lt;&lt; 0) /* 读标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_ADDR_10BIT (1u &lt;&lt; 2) /* 10 位地址模式*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_START (1u &lt;&lt; 4) /* 无开始条件*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_IGNORE_NACK (1u &lt;&lt; 5) /* 忽视NACK */ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_READ_ACK (1u &lt;&lt; 6) /* 读的时候不发送ACK */ +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>使用示例如下所示:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">#define AHT10_ADDR 0x38 /* 从机地址*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 读传感器寄存器数据*/ +</span></span><span class="line"><span class="cl">static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t +</span></span><span class="line"><span class="cl">*buf) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs; +</span></span><span class="line"><span class="cl"> msgs.addr = AHT10_ADDR; /* 从机地址*/ +</span></span><span class="line"><span class="cl"> msgs.flags = RT_I2C_RD; /* 读标志*/ +</span></span><span class="line"><span class="cl"> msgs.buf = buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl"> msgs.len = len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl"> /* 调用I2C设备接口传输数据*/ +</span></span><span class="line"><span class="cl"> if (rt_i2c_transfer(bus, &amp;msgs, 1) == 1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return RT_EOK; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return -RT_ERROR; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七i2c-总线设备使用示例">七、I2C 总线设备使用示例 +</h2><p>I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:</p> +<ol> +<li>首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。</li> +<li>控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() +这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">/*</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序清单:</span> <span class="err">这是一个</span><span class="n">I2C</span> <span class="err">设备使用例程</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">例程导出了</span><span class="n">i2c_aht10_sample</span> <span class="err">命令到控制终端</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令调用格式:</span> <span class="n">i2c_aht10_sample</span> <span class="n">i2c1</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令解释:</span> <span class="err">命令第二个参数是要使用的</span><span class="n">I2C总线设备名称</span><span class="err">,</span> <span class="err">为空则使用默认的</span><span class="n">I2C总线设备</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序功能:</span> <span class="err">通过</span><span class="n">I2C</span> <span class="err">设备读取温湿度传感器</span><span class="n">aht10</span> <span class="err">的温湿度数据并打印</span> +</span></span><span class="line"><span class="cl"><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtdevice.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_ADDR 0x38 /* 从机地址*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_GET_DATA 0xAC /* 获取数据命令*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">i2c_bus</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> <span class="o">/*</span> <span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_bool_t</span> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_FALSE</span><span class="p">;</span> <span class="o">/*</span> <span class="err">传感器初始化状态</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">写传感器寄存器</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">write_reg</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">reg</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">reg</span><span class="p">;</span> <span class="o">//</span><span class="n">cmd</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_WR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">读传感器寄存器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">read_regs</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">len</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">buf</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_RD</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">read_temp_humi</span><span class="p">(</span><span class="ne">float</span> <span class="o">*</span><span class="n">cur_temp</span><span class="p">,</span> <span class="ne">float</span> <span class="o">*</span><span class="n">cur_humi</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_GET_DATA</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">/*</span> <span class="err">发送命令</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_regs</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> <span class="o">/*</span> <span class="err">获取传感器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">湿度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_humi</span> <span class="o">=</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">12</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span> <span class="o">|</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf0</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">*</span> <span class="mf">100.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span><span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">温度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_temp</span> <span class="o">=</span> <span class="p">((</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="o">*</span> <span class="mf">200.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">)</span><span class="o">-</span> <span class="mi">50</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">aht10_init</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">查找</span><span class="n">I2C总线设备</span><span class="err">,</span> <span class="err">获取</span><span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">i2c_bus</span> <span class="o">=</span> <span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="p">)</span><span class="n">rt_device_find</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i2c_bus</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;can&#39;t find </span><span class="si">%s</span><span class="s2"> device!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_NORMAL_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x08</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_CALIBRATION_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_TRUE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">i2c_aht10_sample</span><span class="p">(</span><span class="ne">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">char</span> <span class="n">name</span><span class="p">[</span><span class="n">RT_NAME_MAX</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">AHT10_I2C_BUS_NAME</span><span class="p">,</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">传感器初始化</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">aht10_init</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">读取温湿度数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_temp_humi</span><span class="p">(</span><span class="o">&amp;</span><span class="n">temperature</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor humidity : </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2"> </span><span class="si">%%</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span> <span class="n">temperature</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="o">-</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;initialize sensor failed!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">导出到</span><span class="n">msh</span> <span class="err">命令列表中</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">i2c_aht10_sample</span><span class="p">,</span> <span class="n">i2c</span> <span class="n">aht10</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>学习资料参考:<a class="link" href="https://item.jd.com/10022312146340.html" target="_blank" rel="noopener" +>《嵌入式系统设计》</a>、<a class="link" href="https://club.rt-thread.org/index.html" target="_blank" rel="noopener" +>RT-Thread</a></p>RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/cover.jpg" alt="Featured image of post RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)" /><h2 id="一初识rt-thread">一、初识RT-Thread +</h2><p><code>做世界级的 OS,让万物互联,信息畅通无阻。</code> +<code>成为未来 AIoT 领域最为主流的操作系统平台。</code></p> +<h4 id="1简介">1.简介 +</h4><blockquote> +<p>RT-Thread 是一个集<code>实时操作系统(RTOS)内核、中间件组件和开发者社区于一体</code>的技术平台,由<code>熊谱翔先生</code>带领并集合开源社区力量开发而成,RT-Thread 也是一个<code>组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性</code>的<code>物联网操作系统</code>。</p> +</blockquote> +<h4 id="2前景">2.前景 +</h4><blockquote> +<p>RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个<code>国内最大的嵌入式开源社区</code>,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人<code>自主开发</code>、国内最成熟稳定和装机量最大的<code>开源 RTOS</code>。</p> +</blockquote> +<h4 id="3软件生态">3.软件生态 +</h4><blockquote> +<p>RT-Thread 拥有<code>良好的软件生态</code>,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。</p> +</blockquote> +<h2 id="二实验准备">二、实验准备 +</h2><ul> +<li>编程工具:<code>RT-Thread studio</code></li> +<li>开发板:<code>潘多拉STM32L475</code></li> +</ul> +<hr> +<h2 id="三实验需求">三、实验需求 +</h2><ul> +<li>1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 +右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。</li> +<li>2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。</li> +</ul> +<h2 id="四操作流程">四、操作流程 +</h2><h4 id="1新建rt-thread工程">1.新建RT-Thread工程 +</h4><p><img src="https://img-blog.csdnimg.cn/85370c1057554323ba75dd83c3d1844f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rt-thread-studio界面介绍">2.RT-Thread Studio界面介绍 +</h4><p><img src="https://img-blog.csdnimg.cn/b24064da660f40b5b00e9e0f03d4f1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="3代码编写">3.代码编写 +</h4><p><img src="https://img-blog.csdnimg.cn/c556436b0d44443686dafa3a0f389bd5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="4烧录">4.烧录 +</h4><p><img src="https://img-blog.csdnimg.cn/c5ea1524e61e4b92af667e17decd12bb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5串口监视">5.串口监视 +</h4><p><img src="https://img-blog.csdnimg.cn/eae3d5a76ae14aa0a7e6a2d00145024d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="五代码演示">五、代码演示 +</h2><p><code>1.头文件</code></p> +<pre><code>#include &lt;rtthread.h&gt; +#include &lt;rtdevice.h&gt; +#include &lt;board.h&gt; +</code></pre> +<p><code>2.宏定义</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">//</span><span class="err">按键初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">电机初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">蜂鸣器初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_BEEP GET_PIN(B,2)//PB2:BEEP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">enum</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_STOP</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_LEFT</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_RIGHT</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>3.void motor_ctrl(rt_uint8_t turn) //电机控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void motor_ctrl(rt_uint8_t turn) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (turn == MOTOR_STOP) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_LEFT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_RIGHT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_HIGH); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;err parameter ! Please enter 0-2.&#34;); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void beep_ctrl(rt_uint8_t on) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (on) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.void irq_callback(void *args) // 中断回调函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void irq_callback(void *args) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> rt_uint32_t sign = (rt_uint32_t)args; +</span></span><span class="line"><span class="cl"> switch (sign) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> case PIN_KEY0: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_LEFT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY0 interrupt. motor turn left.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY1: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_RIGHT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY1 interrupt. motor turn right.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY2: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_STOP); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY2 interrupt. motor stop.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> default: +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;error sign= %d !&#34;, sign); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> unsigned int count = 1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置电机控制引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置蜂鸣器引脚为输出模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键中断模式与中断回调函数*/ +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 使能中断*/ +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> while (count &gt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(50); +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;WK_UP pressed. beep on.&#34;); +</span></span><span class="line"><span class="cl"> beep_ctrl(1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> beep_ctrl(0); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(10); +</span></span><span class="line"><span class="cl"> count++; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六原理讲解">六、原理讲解 +</h2><p><!-- raw HTML omitted -->通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 +1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 +2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。<!-- raw HTML omitted --></p> +<table> +<thead> +<tr> +<th>按键</th> +<th>功能</th> +</tr> +</thead> +<tbody> +<tr> +<td>KEY0</td> +<td>电机左转</td> +</tr> +<tr> +<td>KEY1</td> +<td>电机右转</td> +</tr> +<tr> +<td>KEY2</td> +<td>电机停止</td> +</tr> +<tr> +<td>WK_UP</td> +<td>蜂鸣器响</td> +</tr> +</tbody> +</table>RT-Thread Studio使用 2.内核实战篇(线程)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/cover.jpg" alt="Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)" /><p>详细原理参考:<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<h2 id="一线程创建">一、线程创建 +</h2><h4 id="1函数原型">1、函数原型 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 线程创建 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_thread_t</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>首先我们来看看线程创建函数返回值类型:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/de83fe0a4aad4ffe9989eacdf86e96df.png" +loading="lazy" +></p> +<blockquote> +<p>可以看到线程创建函数的返回值类型为:<code>rt_thread_t</code>,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1dfc5d7964484cae9cc44d8067ffcdd0.png" +loading="lazy" +></p> +<h4 id="2线程定义">2、线程定义 +</h4><p>那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1_ptr</span> <span class="o">=</span> <span class="nb">NULL</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>接下来就是我们给进程控制块传参了</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/90d481586b964d01958c9a14a2bd4695.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/7f39dba639bb4c5faeed06524f57a60d.png" +loading="lazy" +></p> +<h4 id="3线程创建判断">3、线程创建判断 +</h4><p>由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功</p> +<p>我们先来看下线程返回值(如下图)</p> +<blockquote> +<p>如果<code>成功创建</code>的话,返回值是会返回我们所创建的线程对象的</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b19a07990b2240728d423f2c7064d47c.png" +loading="lazy" +></p> +<blockquote> +<p>如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/faf3ad30a6f046638db1c77a0c8275a4.png" +loading="lazy" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span><span class="p">(</span><span class="n">th1_ptr</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//错误信息打印 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_thread_create create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> <span class="c1">// 设定当线程th1_ptr创建失败后,返回一个空间不足的标志 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">//打印debug调试信息 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_thread_create create successed ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4线程入口函数">4、线程入口函数 +</h4><p>我们在线程的入口处理函数写一个循环函数:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源</code></p> +<ul> +<li>编译,串口观察</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4c5556830c644e48bfa76008218fb680.png" +loading="lazy" +></p> +<p>由于RTT studio有内置的串口终端,我们直接打开</p> +<p><img src="https://img-blog.csdnimg.cn/cd4fd4b573c0421a88a73d9f8e7160dd.png" +loading="lazy" +></p> +<p>终端输入list_thread可以查看所有的线程</p> +<p><img src="https://img-blog.csdnimg.cn/edae1f6480c54759915145477406f17d.png" +loading="lazy" +></p> +<h4 id="5总结">5、总结 +</h4><p>这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?</p> +<p>其实我们再看th_demo线程的状态可以看到是<code>init</code>,参考<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<p><code>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</code></p> +<p>其实这句话就表明当<code>线程处于初始化状态下是不参与系统调度</code>的!</p> +<h4 id="6补充">6、补充 +</h4><p>线程错误码:</p> +<p><img src="https://img-blog.csdnimg.cn/f32f5440cb604b2d8eea4a4546d977b0.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<h2 id="二线程启动">二、线程启动 +</h2><p>函数原型</p> +<p>在主函数中加入命令,使线程进入就绪态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_thread_startup(th1_ptr); +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为<code>挂起态</code></p> +<p><img src="https://img-blog.csdnimg.cn/f5f40f386046488f89e56ab8ee8db6d4.png" +loading="lazy" +></p> +<p><code>解释:</code>虽然我们调用<code>rt_thread_startup</code>函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了<code>rt_thread_mdelay</code>函数使其有一定时间的休眠,从而进入了挂起态`</p> +<h2 id="三初始化线程">三、初始化线程 +</h2><p><code>rt_thread_init</code></p> +<h4 id="1函数声明">1、函数声明 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 模板函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_err_t</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="k">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="kr">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2函数定义">2、函数定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th2</span><span class="p">,</span><span class="s">&#34;th2_demo&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">th2_stack</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">th2_stack</span><span class="p">),</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>此处我们需要定义一个ret整型变量用于<code>rt_thread_init</code>的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b7ce209e742948a398d235d4fd799279.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/06a57b94d88c4cdf97f9a431d1578862.png" +loading="lazy" +></p> +<h4 id="3线程入口函数">3、线程入口函数 +</h4><p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">10</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4判断创建状态">4、判断创建状态 +</h4><p>静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用<code>rt_thread_startup</code>函数使线程2进入就绪态,并执行线程处理函数。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">if(ret &lt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> LOG_E(&#34;rt2_thread_create create failed ...\n&#34;); // 错误信息打印 +</span></span><span class="line"><span class="cl"> return ret; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> LOG_D(&#34;rt_thread2_create create successes ...\n&#34;); +</span></span><span class="line"><span class="cl"> rt_thread_startup(&amp;th2); // 创建成功后,我们开启线程,使其进入就绪态 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启</p> +</blockquote> +<h4 id="5实验结果">5、实验结果 +</h4><blockquote> +<p>分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/861754f210a74896a6d63d20fbb629f0.png" +loading="lazy" +></p> +<blockquote> +<p>线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/85333e4d1b1942d6a59b10e528797ecc.png" +loading="lazy" +></p>时钟管理(原理+实战)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/Wed, 13 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/cover.jpg" alt="Featured image of post 时钟管理(原理+实战)" /><h2 id="一时钟节拍">一、时钟节拍 +</h2><p>任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。</p> +<p>RT-Thread 中,时钟节拍的长度可以根据 <code>RT_TICK_PER_SECOND</code> 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,<code>系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!</code></p> +<p>rtconfig.h配置文件中定义:</p> +<blockquote> +<ul> +<li> +<p>频率是1000HZ周期是1/1000 s</p> +</li> +<li> +<p>所以节拍是1ms</p> +</li> +<li> +<p>#define RT_ <em>TiCK</em> PER_ SECOND 1000</p> +</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d00c117cba6245909ad5fdab19c9bf74.png" +loading="lazy" +></p> +<h4 id="1void-systick_handler">1、void SysTick_Handler() +</h4><p>在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行<code>void SysTick_Handler</code>(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)</p> +<p><img src="https://img-blog.csdnimg.cn/c97f508be8c844a7bfa08cff57233dc1.png" +loading="lazy" +></p> +<blockquote> +<p>可以发现在<code>void SysTick_Handler()</code>这个函数中,首先会执行中断入口函数,然后<code>void rt_tick_increase</code>对<code>rt_tick</code>(系统滴答时钟,初值为0,静态<code>全局变量</code>)进行自加操作,会记录从启动到现在的时钟节拍数</p> +</blockquote> +<h4 id="2void-rt_tick_increase">2、void rt_tick_increase() +</h4><p><img src="https://img-blog.csdnimg.cn/b7122a14e60444e29f36e106bfb5166d.png" +loading="lazy" +></p> +<p><code>也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断 </code></p> +<h4 id="3rt_tick_getvoid">3、rt_tick_get(void); +</h4><p>名称:获取系统统计函数</p> +<p>功能:返回当前操作系统的时钟数</p> +<p>返回值:返回当前时钟数</p> +<p><img src="https://img-blog.csdnimg.cn/dd9e18ad7b4942ce9af13f1870fcc232.png" +loading="lazy" +></p> +<h2 id="二定时器管理">二、定时器管理 +</h2><h4 id="1概念">1、概念 +</h4><p>定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有<code>硬件定时器</code>和<code>软件定时器</code>之分:</p> +<p>1)<strong>硬件定时器</strong>是芯片本身提供的定时功能。<code>一般是由外部晶振(HSE)提供给芯片输入时钟</code>,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是<code>中断触发方式</code>。</p> +<p>2)<strong>软件定时器</strong>是由<code>操作系统提供的一类系统接口</code>,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。</p> +<p>RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即<code>定时数值必须是 OS Tick 的整数倍</code>,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。</p> +<h4 id="2rt-thread定时器介绍">2、RT-Thread定时器介绍 +</h4><p>RT-Thread 的定时器提供两类定时器机制:</p> +<p>第一类是<code>单次触发</code>定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 +第二类是<code>周期触发</code>定时器,这类定时器会周期性的触发定时器事件,直到<code>用户手动的停止</code>,否则将永远持续执行下去。</p> +<p>另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 <code>HARD_TIMER </code>模式(硬件定时器模式)与<code> SOFT_TIMER</code> 模式(软件定时器模式),如下图。</p> +<p><img src="https://img-blog.csdnimg.cn/36887975b53c4dc684343c70a2f8db09.png" +loading="lazy" +></p> +<p>1)HARD_TIMER 模式:中断上下文</p> +<p>HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数<code>RT_TIMER_FLAG_HARD_TIMER</code>来指定。</p> +<p>在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:<code>执行时间应该尽量短,执行时不应导致当前上下文挂起、等待</code>。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。</p> +<p>2)SOFT_TIMER 模式:线程上下文</p> +<p>SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。</p> +<p>该模式被启用后,系统会在<code>初始化时创建一个 timer 线程</code>,然后 <code>SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行</code>。可以在初始化 / 创建定时器时使用参数 <code>RT_TIMER_FLAG_SOFT_TIMER </code>来指定设置 <code>SOFT_TIMER</code> 模式。</p> +<h4 id="3定时器源码分析">3、定时器源码分析 +</h4><p>1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/0ee79523a62540a7a18155a0d9010365.png" +loading="lazy" +></p> +<p>2)rt_system_timer_init(硬件定时器初始化)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_system_timer_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span><span class="c1">// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_list_init</span><span class="p">(</span><span class="n">rt_timer_list</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)rt_system_timer_thread_init(软件定时器初始化)</p> +<p><img src="https://img-blog.csdnimg.cn/68e5d39a7cf94149a474f05b0f370717.png" +loading="lazy" +></p> +<h4 id="4定时器工作机制">4、定时器工作机制 +</h4><p>下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的<code>全局变量</code>:</p> +<p>(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);</p> +<p>(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照<code>以超时时间排序</code>的方式<code>插入到 rt_timer_list 链表</code>中。</p> +<p>如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。</p> +<p><img src="https://img-blog.csdnimg.cn/bb6521cccf884694867fd32a5c76da27.png" +loading="lazy" +></p> +<p>而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),<code>50 个 tick 以后,rt_tick 从 20 增长到 70</code>,与 <code>Timer1 的 timeout 值相等</code>,这时会<code>触发与 Timer1 定时器相关联的超时函数</code>,同时将 <code>Timer1 从 rt_timer_list 链表上删除</code>。</p> +<p>同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。</p> +<p>如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 <code>timeout=rt_tick+300=330</code>, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:</p> +<p><img src="https://img-blog.csdnimg.cn/515005f47d5148848a7ea4fe883b6f39.png" +loading="lazy" +></p> +<h4 id="5定时器相关接口">5、定时器相关接口 +</h4><p>1)<strong>动态创建定时器</strong></p> +<p>动态创建声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>详细函数定义:</p> +<p><img src="https://img-blog.csdnimg.cn/87411b4f65564541a22792b8fc676ec1.png" +loading="lazy" +></p> +<p>查看flag定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_ONE_SHOT 0x0 </span><span class="c1">// 单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_PERIODIC 0x2 </span><span class="c1">// 周期性触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_HARD_TIMER 0x0 </span><span class="c1">// 硬件定时器模式 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_SOFT_TIMER 0x4 </span><span class="c1">// 软件定时器模式 +</span></span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>同时这里我们注意到<code>rt_timer_create</code>这个函数的返回值是<code>rt_timer_t</code>,通过查找定义可以发现该类型是通过typedef重命名的</p> +<p>也就是说<code>struct rt_timer</code> &lt;=&gt;<code>*rt_timer_t</code></p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">rt_timer</span> <span class="o">*</span><span class="kt">rt_timer_t</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; inherit from rt_object */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_list_t</span> <span class="n">row</span><span class="p">[</span><span class="n">RT_TIMER_SKIP_LIST_LEVEL</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout_func</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">);</span> <span class="cm">/**&lt; timeout function */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">;</span> <span class="cm">/**&lt; timeout function&#39;s parameter */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">init_tick</span><span class="p">;</span> <span class="cm">/**&lt; timer timeout tick */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout_tick</span><span class="p">;</span> <span class="cm">/**&lt; timeout tick */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2)<strong>删除定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_timer_delete(rt_timer_t timer); +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:返回操作系统的状态,成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/71ccf0b21d70422fa817b7f9ae7d6843.png" +loading="lazy" +></p> +<p>3)<strong>动态创建定时器演示</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义 )。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写中断回调函数(超时函数) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 返回值结构图定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>4)<strong>开启定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/3542f82f0cc84f4f9c74b871c17753fe.png" +loading="lazy" +></p> +<p>5)实例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在超时函数中编写代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息</p> +<p>6)<strong>静态创建定时器</strong></p> +<p>函数定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们看下<code>rt_timer_init</code>这个函数的返回值和参数</p> +<p>返回值:void</p> +<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">timer</td> +<td style="text-align:center">结构体指针类型</td> +</tr> +<tr> +<td style="text-align:center">name</td> +<td style="text-align:center">名字</td> +</tr> +<tr> +<td style="text-align:center">timeout</td> +<td style="text-align:center">超时回调函数指针</td> +</tr> +<tr> +<td style="text-align:center">parameter</td> +<td style="text-align:center">传递给超时回调函数的参数</td> +</tr> +<tr> +<td style="text-align:center">time</td> +<td style="text-align:center">定时器时间</td> +</tr> +<tr> +<td style="text-align:center">flag</td> +<td style="text-align:center">定时器标志</td> +</tr> +</tbody> +</table> +<p>7)<strong>脱离函数</strong>(静态创建时使用)</p> +<p>描述:当<code>静态创建</code>的定时器不需要在使用时,我们调用下面这个函数接口</p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_detach</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>返回值:成功返回0,失败返回1</p> +<p>8)<strong>定时器控制</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> <span class="kt">int</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>cmd命令定义查看</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_TIME 0x0 </span><span class="cm">/**&lt; set timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_TIME 0x1 </span><span class="cm">/**&lt; get timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_ONESHOT 0x2 </span><span class="cm">/**&lt; change timer to one shot */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_PERIODIC 0x3 </span><span class="cm">/**&lt; change timer to periodic */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_STATE 0x4 </span><span class="cm">/**&lt; get timer run state active or deactive*/</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cb30a12c60e24f51a5ef081c296347bd.png" +loading="lazy" +></p> +<p>实例:</p> +<blockquote> +<p>查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/67007c956ebd48478e44b9233abd8efe.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> <span class="n">tm2</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm2_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">10</span><span class="p">)</span><span class="c1">// 当flags标志位位10时,设置单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_ONESHOT</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_TIME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">timeout</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[%u]tm2_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="nf">rt_tick_get</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 动态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 静态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span><span class="s">&#34;tm2_demo&#34;</span><span class="p">,</span><span class="n">tm2_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="三高精度延时">三、高精度延时 +</h2><blockquote> +<p><code>注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间</code></p> +</blockquote> +<ul> +<li>函数声明:<code>void rt_hw_us_delay(rt_uint32_t us);</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/43a92b7bdd884f18bf6ce522214cb520.png" +loading="lazy" +></p> +<ul> +<li>应用场景:应用于某些场景下对高精度延时有要求的情况下</li> +</ul>env工具学习https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post env工具学习" /><h4 id="一基础配置">一、基础配置 +</h4><p>1.首先需要下载git并配置好相应的环境变量</p> +<p>2.双击env,在setting中设置</p> +<p><img src="https://img-blog.csdnimg.cn/709a490d50c24945a2b06409d51b3209.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这样就可以指定文件夹打开env工具了</p> +<h4 id="二基本命令学习">二、基本命令学习 +</h4><p>1.scons:编译</p> +<p><img src="https://img-blog.csdnimg.cn/976aba29a258481d9128f4b984f78139.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]" +></p> +<p><code>(1)scons:</code>编译并打印相关内部信息 +<code>(2)scons -c:</code>清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +<code>(3)scons -s:</code>编译而不打印具体的内部命令 +<code>(4)scons --target=XXX:</code>使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=iar +</span></span><span class="line"><span class="cl">scons --target=mdk4 +</span></span><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(5)scons -jN:</code>多线程编译目标,在多核计算机上可以使用此命令加快编译速度</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons -j4 //双核编译工程 +</span></span></code></pre></td></tr></table> +</div> +</div><p><!-- raw HTML omitted -->注意:一般不建议使用,容易将编译信息和错误混杂<!-- raw HTML omitted --> +<code>(6)scons --dist:</code>搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set RTT_CC=keil +</span></span><span class="line"><span class="cl">set RTT_EXEC_PATH=C:/Keilv5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.menuconfig +打开菜单配置界面,可用户自定义模块</p> +<p>4.scons进阶学习 +scons内置函数</p> +<ul> +<li> +<p>GetCurrentDir(): +获取当前路径。</p> +</li> +<li> +<p>Glob(&rsquo;*.c&rsquo;): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。</p> +</li> +<li> +<p>GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。</p> +</li> +<li> +<p>Split(str): +将字符串 str 分割成一个列表 list。</p> +</li> +<li> +<p>DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +<code>DefineGroup()</code> 函数的参数描述:</p> +</li> +</ul> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th style="text-align:center"><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td style="text-align:center">Group 的名字</td> +</tr> +<tr> +<td>src</td> +<td style="text-align:center">Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件</td> +</tr> +<tr> +<td>depend</td> +<td style="text-align:center">Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现</td> +</tr> +<tr> +<td>parameters</td> +<td style="text-align:center">配置其他参数,可取值见下表,实际使用时不需要配置所有参数</td> +</tr> +</tbody> +</table> +<p>parameters可加入的参数:</p> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>dirs</td> +<td>SConscript 文件路径</td> +</tr> +<tr> +<td>variant_dir</td> +<td>指定生成的目标文件的存放路径</td> +</tr> +<tr> +<td>duiplicate</td> +<td>设定是否拷贝或链接源文件到 variant_dir</td> +</tr> +</tbody> +</table> \ No newline at end of file diff --git a/categories/rt-thread/index_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_120x120_fill_q75_box_smart1.jpg b/categories/rt-thread/index_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_120x120_fill_q75_box_smart1.jpg new file mode 100644 index 000000000..3daae396d Binary files /dev/null and b/categories/rt-thread/index_hu2b16bca43ddfa4ef4950ab4bf142af5f_169374_120x120_fill_q75_box_smart1.jpg differ diff --git a/categories/rt-thread/page/1/index.html b/categories/rt-thread/page/1/index.html new file mode 100644 index 000000000..1ff81f2ab --- /dev/null +++ b/categories/rt-thread/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/rt-thread/ + \ No newline at end of file diff --git a/categories/rt-thread/page/2/index.html b/categories/rt-thread/page/2/index.html new file mode 100644 index 000000000..a5b2d40ed --- /dev/null +++ b/categories/rt-thread/page/2/index.html @@ -0,0 +1,57 @@ +Category: RT-Thread - Pager 2 - kurisaW +

Categories

13 pages

RT-Thread

RT-Thread 是一款主要由中国开源社区主导开发的开源实时操作系统(v3.1.0以及以前版本遵循GPLv2+许可协议,v3.1.0以后版本遵循 Apache License 2.0 开源许可协议)。实时线程操作系统不仅仅是一个单一的实时操作系统内核,它也是一个完整的应用系统,包含了实时、嵌入式系统相关的各个组件:TCP/IP协议栈,libc接口,图形用户界面等。

\ No newline at end of file diff --git a/categories/rt-thread/page/3/index.html b/categories/rt-thread/page/3/index.html new file mode 100644 index 000000000..52cc3234d --- /dev/null +++ b/categories/rt-thread/page/3/index.html @@ -0,0 +1,57 @@ +Category: RT-Thread - Pager 3 - kurisaW +

Categories

13 pages

RT-Thread

RT-Thread 是一款主要由中国开源社区主导开发的开源实时操作系统(v3.1.0以及以前版本遵循GPLv2+许可协议,v3.1.0以后版本遵循 Apache License 2.0 开源许可协议)。实时线程操作系统不仅仅是一个单一的实时操作系统内核,它也是一个完整的应用系统,包含了实时、嵌入式系统相关的各个组件:TCP/IP协议栈,libc接口,图形用户界面等。

\ No newline at end of file diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453.jpg" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453.jpg" new file mode 100644 index 000000000..40ad927b6 Binary files /dev/null and "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453.jpg" differ diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_250x150_fill_q75_box_smart1.jpg" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..e6c5089eb Binary files /dev/null and "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.1151b3e57f615aa62cf8997d014c3453_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.html" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.html" new file mode 100644 index 000000000..553ae7c63 --- /dev/null +++ "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.html" @@ -0,0 +1,55 @@ +Category: 嵌入式素养提升 - kurisaW +

Categories

1 page

嵌入式素养提升

嵌入式系统(embedded system),是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。

\ No newline at end of file diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" new file mode 100644 index 000000000..40ad927b6 Binary files /dev/null and "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.jpg" differ diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" new file mode 100644 index 000000000..ee5aeed43 --- /dev/null +++ "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index.xml" @@ -0,0 +1,10 @@ +嵌入式素养提升 on kurisaWhttps://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/Recent content in 嵌入式素养提升 on kurisaWHugo -- gohugo.ioenSat, 04 Nov 2023 00:00:00 +0000【嵌入式素养提升】MPU与MCUhttps://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/<img src="https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover.jpg" alt="Featured image of post 【嵌入式素养提升】MPU与MCU" /><h2 id="mpu与mcu">MPU与MCU +</h2><p>MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。</p> +<p>但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。</p> +<p>在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。</p> +<p>由于主要完成“控制”相关的任务,所以称为 <code>Controller</code>。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。</p> +<p>而<code>Processor</code>,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。</p> +<p>以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。</p> +<p>为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。</p> +<p>从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。</p> +<p>总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。</p> \ No newline at end of file diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_120x120_fill_q75_box_smart1.jpg" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d9442ed85 Binary files /dev/null and "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/index_hu3d03a01dcc18bc5be0e67db3d8d209a6_246672_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" new file mode 100644 index 000000000..5ceeeb042 --- /dev/null +++ "b/categories/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/ + \ No newline at end of file diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b.jpg" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b.jpg" new file mode 100644 index 000000000..e0fa0f6d7 Binary files /dev/null and "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b.jpg" differ diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b_hu5ce82528a703b85156df47752b58958d_1024043_250x150_fill_q75_box_smart1.jpg" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b_hu5ce82528a703b85156df47752b58958d_1024043_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..6e6ceed7c Binary files /dev/null and "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.8574ba2db88f507de780fe1de9aae48b_hu5ce82528a703b85156df47752b58958d_1024043_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.html" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.html" new file mode 100644 index 000000000..cb003e9f5 --- /dev/null +++ "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.html" @@ -0,0 +1,56 @@ +Category: 数据结构与算法 - kurisaW +

Categories

8 pages

数据结构与算法

数据结构(英语:data structure)是计算机中存储、组织数据的方式。数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素集合。它包含三方面的内容,逻辑关系、存储关系及操作。

\ No newline at end of file diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.jpg" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.jpg" new file mode 100644 index 000000000..e0fa0f6d7 Binary files /dev/null and "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.jpg" differ diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.xml" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.xml" new file mode 100644 index 000000000..871326a47 --- /dev/null +++ "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index.xml" @@ -0,0 +1,5039 @@ +数据结构与算法 on kurisaWhttps://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/Recent content in 数据结构与算法 on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index_hu5ce82528a703b85156df47752b58958d_1024043_120x120_fill_q75_box_smart1.jpg" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index_hu5ce82528a703b85156df47752b58958d_1024043_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..349ca3f7e Binary files /dev/null and "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/index_hu5ce82528a703b85156df47752b58958d_1024043_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/1/index.html" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/1/index.html" new file mode 100644 index 000000000..9cf7bd162 --- /dev/null +++ "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/ + \ No newline at end of file diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/2/index.html" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/2/index.html" new file mode 100644 index 000000000..a2910c2c8 --- /dev/null +++ "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/page/2/index.html" @@ -0,0 +1,56 @@ +Category: 数据结构与算法 - Pager 2 - kurisaW +

Categories

8 pages

数据结构与算法

数据结构(英语:data structure)是计算机中存储、组织数据的方式。数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素集合。它包含三方面的内容,逻辑关系、存储关系及操作。

\ No newline at end of file diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3.jpg" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3.jpg" new file mode 100644 index 000000000..ba30d5f1d Binary files /dev/null and "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3.jpg" differ diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3_huf59e7bbb83d193d0a091a24123e64082_233384_250x150_fill_q75_box_smart1.jpg" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3_huf59e7bbb83d193d0a091a24123e64082_233384_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..78a7985b3 Binary files /dev/null and "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.76face4f471e6fb9574593e0b8d299f3_huf59e7bbb83d193d0a091a24123e64082_233384_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.html" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.html" new file mode 100644 index 000000000..a28956b0c --- /dev/null +++ "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.html" @@ -0,0 +1,55 @@ +Category: 网络编程 - kurisaW +

Categories

1 page

网络编程

网络编程是指利用计算机网络进行程序设计与开发的技术。随着计算机网络的普及和互联网的发展,网络编程已经成为现代软件开发中不可或缺的一部分。通过网络编程,可以实现不同计算机之间的数据传输、文件共享、远程控制等功能,为人们的日常生活和工作提供了便利。

\ No newline at end of file diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.jpg" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.jpg" new file mode 100644 index 000000000..ba30d5f1d Binary files /dev/null and "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.jpg" differ diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.xml" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.xml" new file mode 100644 index 000000000..50a452898 --- /dev/null +++ "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index.xml" @@ -0,0 +1,56 @@ +网络编程 on kurisaWhttps://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/Recent content in 网络编程 on kurisaWHugo -- gohugo.ioenMon, 10 Apr 2023 00:00:00 +0000【网络编程】OSI七层模型&TCPIP四层模型https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/<img src="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover.jpg" alt="Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型" /><h2 id="osi七层模型">OSI七层模型 +</h2><p>七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。</p> +<h4 id="1物理层">1.物理层 +</h4><p><code>建立、维护、断开物理连接。</code>(由底层网络定义协议)</p> +<p>机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。</p> +<p>应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。</p> +<h4 id="2数据链路层">2.数据链路层 +</h4><p><code>建立逻辑连接、进行硬件地址寻址、差错校验等功能。</code>(由底层网络定义协议)</p> +<p>将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)</p> +<h4 id="3网络层">3.网络层 +</h4><p><code>进行逻辑地址寻址,实现不同网络之间的路径选择。</code></p> +<p>控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)</p> +<h4 id="4传输层">4.传输层 +</h4><p><code>定义传输数据的协议端口号,以及流控和差错校验。</code> +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层</p> +<h4 id="5会话层">5.会话层 +</h4><p><code>建立、管理、终止会话。</code>(在五层模型里面已经合并到了应用层)</p> +<p>不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)</p> +<h4 id="6表示层">6.表示层 +</h4><p><code>数据的表示、安全、压缩。</code>(在五层模型里面已经合并到了应用层)</p> +<p>信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)</p> +<h4 id="7应用层">7.应用层 +</h4><p><code>网络服务与最终用户的一个接口</code></p> +<p>各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)</p> +<hr> +<h2 id="tcpip-四层模型">TCP/IP 四层模型 +</h2><p>TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是<strong>指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇</strong>, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304101020851.png" +loading="lazy" +alt="20201028134158932" +></p> +<p>TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示</p> +<h4 id="1应用层">1.应用层 +</h4><p><code>应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。</code></p> +<ul> +<li>应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次</li> +<li>对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议</li> +<li>应用层还能加密、解密、格式化数据</li> +<li>应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源</li> +</ul> +<h4 id="2传输层">2.传输层 +</h4><p><code>作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用</code></p> +<h4 id="3网络层-1">3.网络层 +</h4><p><code>网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能</code></p> +<h4 id="4网络接口层">4.网络接口层 +</h4><p><code>在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路</code></p> \ No newline at end of file diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index_huf59e7bbb83d193d0a091a24123e64082_233384_120x120_fill_q75_box_smart1.jpg" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index_huf59e7bbb83d193d0a091a24123e64082_233384_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..8c3d53d72 Binary files /dev/null and "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/index_huf59e7bbb83d193d0a091a24123e64082_233384_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\347\275\221\347\273\234\347\274\226\347\250\213/page/1/index.html" "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/page/1/index.html" new file mode 100644 index 000000000..be7ace67d --- /dev/null +++ "b/categories/\347\275\221\347\273\234\347\274\226\347\250\213/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/ + \ No newline at end of file diff --git "a/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486.jpg" "b/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486.jpg" new file mode 100644 index 000000000..ca0118870 Binary files /dev/null and "b/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486.jpg" differ diff --git "a/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486_hu153802b2c270621309055cfacc627383_635717_250x150_fill_q75_box_smart1.jpg" "b/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486_hu153802b2c270621309055cfacc627383_635717_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..7213bf245 Binary files /dev/null and "b/categories/\350\265\204\350\256\257/index.3a492bef61023651ee14d2416606c486_hu153802b2c270621309055cfacc627383_635717_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\350\265\204\350\256\257/index.html" "b/categories/\350\265\204\350\256\257/index.html" new file mode 100644 index 000000000..a3c4fb343 --- /dev/null +++ "b/categories/\350\265\204\350\256\257/index.html" @@ -0,0 +1,55 @@ +Category: 资讯 - kurisaW +

Categories

1 page

资讯

在这里会存放一些有关嵌入式领域的相关实用资讯和转载文章

\ No newline at end of file diff --git "a/categories/\350\265\204\350\256\257/index.jpg" "b/categories/\350\265\204\350\256\257/index.jpg" new file mode 100644 index 000000000..ca0118870 Binary files /dev/null and "b/categories/\350\265\204\350\256\257/index.jpg" differ diff --git "a/categories/\350\265\204\350\256\257/index.xml" "b/categories/\350\265\204\350\256\257/index.xml" new file mode 100644 index 000000000..5744c36b1 --- /dev/null +++ "b/categories/\350\265\204\350\256\257/index.xml" @@ -0,0 +1,21 @@ +资讯 on kurisaWhttps://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/Recent content in 资讯 on kurisaWHugo -- gohugo.ioenMon, 03 Apr 2023 00:00:00 +0000【资讯】汇总一些嵌入式相关的公司https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/<img src="https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/cover.jpg" alt="Featured image of post 【资讯】汇总一些嵌入式相关的公司" /><blockquote> +<p>来源:https://zhuanlan.zhihu.com/p/585079427</p> +</blockquote> +<h2 id="1芯片行业">1.芯片行业 +</h2><p>目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。</p> +<p>代表性公司:</p> +<p>(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等</p> +<p>(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等</p> +<h2 id="2人工智能相关行业">2.人工智能相关行业 +</h2><p>(1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。</p> +<p>(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等</p> +<h2 id="3消费电子行业">3.消费电子行业 +</h2><p>消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等</p> +<h2 id="4传统汽车行业">4.传统汽车行业 +</h2><p>传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等</p> +<h2 id="5国企和军工">5.国企和军工 +</h2><p>国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。</p> +<h2 id="6传统电子电器类">6.传统电子电器类 +</h2><p>这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等</p> +<h2 id="7网络及通信设备">7.网络及通信设备 +</h2><p>主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等</p> \ No newline at end of file diff --git "a/categories/\350\265\204\350\256\257/index_hu153802b2c270621309055cfacc627383_635717_120x120_fill_q75_box_smart1.jpg" "b/categories/\350\265\204\350\256\257/index_hu153802b2c270621309055cfacc627383_635717_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..1501be781 Binary files /dev/null and "b/categories/\350\265\204\350\256\257/index_hu153802b2c270621309055cfacc627383_635717_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/categories/\350\265\204\350\256\257/page/1/index.html" "b/categories/\350\265\204\350\256\257/page/1/index.html" new file mode 100644 index 000000000..a2eb520fe --- /dev/null +++ "b/categories/\350\265\204\350\256\257/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/ + \ No newline at end of file diff --git a/documents/index.html b/documents/index.html new file mode 100644 index 000000000..d001ece52 --- /dev/null +++ b/documents/index.html @@ -0,0 +1,23 @@ +Documents +

Documents

+

说明

这里我存放了一些个人搜集的文档资源,支持PDF在线查看,同时也欢迎各位在评论区留下相关资源链接!

由于构建方式使用的是PDF.js插件,是为html5实现的在线预览pdf框架,所以使用的前提是浏览器要支持html5。该插件不需要任何本地支持,对浏览器的兼容性也比较好(低版本的IE浏览器不支持)。

配置仓库入口:https://github.com/kurisaW/Npdf

注:目前本博客的pdf资源已部分上传至infinityfree服务器,较之pdf.js有更快响应速度,后续考虑国内CDN加速,当然想要学习和了解pdf.js的构建方式也可参考此仓库Npdf;由于部分pdf文件较大,反应速度慢属于正常现象。

目前上传的PDF资源如下:

精品专栏

C语言专栏

C++专栏

Linux专栏

Git专题

笔试面试专题

操作系统专栏

数据结构与算法专栏

历年软考嵌入式系统设计师真题及答案

联系我

如果你有相关资源想要集合到一个网站以便随时访问而又拘于时间问题没法搭建网站的话,可以与我取得联系,我将帮助你整理好资源,以此为你提供更加便利的阅读!

欢迎你的来访,期待与你有更好的合作!

联系我请移步

+Licensed under CC BY-NC-SA 4.0
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git a/explore/index.html b/explore/index.html new file mode 100644 index 000000000..85b7ce2de --- /dev/null +++ b/explore/index.html @@ -0,0 +1,33 @@ +Explore +

Explore

+

If you have resources or tools that you recommend, you can contribute in the format below

This page’s frontmatter:

1
+2
+3
+4
+5
+
links:
+  - title: Explore
+    description: Here are some links to interesting and useful sites.
+    website: https://kurisaw.github.io/explore/
+    image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
+

image field accepts both local and external images.

+Licensed under CC BY-NC-SA 4.0
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 000000000..dce3cdd85 --- /dev/null +++ b/index.html @@ -0,0 +1,68 @@ +kurisaW +
\ No newline at end of file diff --git a/index.xml b/index.xml new file mode 100644 index 000000000..74cfd6f22 --- /dev/null +++ b/index.xml @@ -0,0 +1,28505 @@ +kurisaWhttps://kurisaw.github.io/Recent content on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduinohttps://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover.jpg" alt="Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino" /><h1 id="瑞萨hmi-board使用vscode开发rtduino结合ssd1306-oled">瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) +</h1><hr> +<h2 id="1准备工作">1.准备工作 +</h2><p>软件环境:</p> +<ul> +<li><a class="link" href="https://github.com/RT-Thread/rt-thread" target="_blank" rel="noopener" +> RT-Thread 主仓代码(需下载至本地)</a></li> +<li>vscode</li> +<li>rt-thread env</li> +</ul> +<p>硬件环境:</p> +<ul> +<li>RA6M3-HMI-Board 开发板</li> +<li>0.96寸 ssd1306 oled 显示屏</li> +</ul> +<h2 id="2工程配置">2.工程配置 +</h2><p>首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要我们提前安装好 ENV 环境,具体细节请参考 <a class="link" href="https://docs.rtduino.com/#/zh/beginner/env?id=env%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba" target="_blank" rel="noopener" +>Env编译环境搭建</a> 。</p> +<p>鼠标右键打开 ENV 工具后,使用 <strong>menuconfig</strong> 命令打开可视化菜单,勾选上 <strong>RTduino</strong> 的使能项,保存并退出</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251.png" +width="1086" +height="392" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123170636251" +class="gallery-image" +data-flex-grow="277" +data-flex-basis="664px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">RT-Thread Configuration +</span></span><span class="line"><span class="cl"> → Hardware Drivers Config +</span></span><span class="line"><span class="cl"> → Onboard Peripheral Drivers +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Compatible with Arduino Ecosystem <span class="o">(</span>RTduino<span class="o">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123171151275" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623.png" +width="1682" +height="768" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173108623" +class="gallery-image" +data-flex-grow="219" +data-flex-basis="525px" +></p> +<h2 id="3开始编译">3.开始编译 +</h2><p>打开 ENV ,同时执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons -j16 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173509831" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>在工程编译完成后会生成一个 <code>.elf</code>后缀的可执行文件,到这里工程的编译就顺利结束了。</p> +<h2 id="4vscode调试配置">4.vscode调试配置 +</h2><p>首先我们需要在 vscode 中安装 <code>Cortex-Debug</code> 插件,打开 vscode 扩展,搜索 <code>Cortex-Debug</code>并安装扩展:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123175244073" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接下来就是安装 <code>pyocd</code> 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 <code>create a launch.json file</code>:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889.png" +width="1385" +height="462" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123180230889" +class="gallery-image" +data-flex-grow="299" +data-flex-basis="719px" +></p> +<p>之后 vscode 会创建一份 <code>launch.json</code> 文件,我们需要替换文件内容为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// Use IntelliSense to learn about possible attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Hover to view descriptions of existing attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.2.0&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;configurations&#34;</span><span class="p">:</span> <span class="p">[</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;HMI-Board&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;cwd&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceFolder}&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;executable&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;request&#34;</span><span class="p">:</span> <span class="s2">&#34;launch&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;cortex-debug&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;runToEntryPoint&#34;</span><span class="p">:</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;targetId&#34;</span><span class="p">:</span> <span class="s2">&#34;R7FA6M3AH&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;servertype&#34;</span><span class="p">:</span> <span class="s2">&#34;pyocd&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;serverpath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/compile/sdk-debugger-pyocd/pyocd.bat&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;armToolchainPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;gdbPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<code>launch.json</code>文件中的部分参数需要根据具体位置配置</p> +<ul> +<li><code>serverpath</code>:这部分路径在前面所安装的 <code>sdk-debugger-pyocd</code>位置</li> +<li><code>armToolchainPath</code>:gcc 工具链,找不到位置的可以<a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>点击此处下载</a></li> +<li><code>gdbPath</code></li> +</ul> +<p>在完成上述配置后就可以点击 <code>F5</code> 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123183906784" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932.png" +width="815" +height="536" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184032932" +class="gallery-image" +data-flex-grow="152" +data-flex-basis="364px" +></p> +<p>到这里 RTduino 就已经成功运行在 RT-Thread 啦!</p> +<h2 id="5demo使用-rtduino-驱动-096寸-ssd1306-oled">5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled +</h2><p>在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过<code>RTduino</code>,并在<code>RT-Thread</code>中使用 <code>Arduino</code> 源码驱动一个 oled 屏幕。</p> +<p>我们接着回到 ENV 中,使用 <code>menuconfig</code>命令打开菜单,同时使用 <code>shift + /</code>打开搜索界面,并且输入:<code>ssd1306</code>关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 <code>Adafruit SSD1306</code>对应的 <code>2</code>选项,进入点击 <code>y</code> 使能:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184834403" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184930394" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p>这样我们就成功把 <code>Adafruit SSD1306</code> 示例库下载到本地了,同时还有一下依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453.png" +width="1720" +height="772" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123185120453" +class="gallery-image" +data-flex-grow="222" +data-flex-basis="534px" +></p> +<p>我们找到路径:<code>rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c</code>,可以看到该文件夹下有一个<code>ssd1306_128x64_i2c.ino</code>文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的<code>arduino_main.cpp</code>文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board<span class="se">\b</span>oard<span class="se">\r</span>tduino<span class="se">\a</span>rduino_main.cpp +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span><span class="lnt">267 +</span><span class="lnt">268 +</span><span class="lnt">269 +</span><span class="lnt">270 +</span><span class="lnt">271 +</span><span class="lnt">272 +</span><span class="lnt">273 +</span><span class="lnt">274 +</span><span class="lnt">275 +</span><span class="lnt">276 +</span><span class="lnt">277 +</span><span class="lnt">278 +</span><span class="lnt">279 +</span><span class="lnt">280 +</span><span class="lnt">281 +</span><span class="lnt">282 +</span><span class="lnt">283 +</span><span class="lnt">284 +</span><span class="lnt">285 +</span><span class="lnt">286 +</span><span class="lnt">287 +</span><span class="lnt">288 +</span><span class="lnt">289 +</span><span class="lnt">290 +</span><span class="lnt">291 +</span><span class="lnt">292 +</span><span class="lnt">293 +</span><span class="lnt">294 +</span><span class="lnt">295 +</span><span class="lnt">296 +</span><span class="lnt">297 +</span><span class="lnt">298 +</span><span class="lnt">299 +</span><span class="lnt">300 +</span><span class="lnt">301 +</span><span class="lnt">302 +</span><span class="lnt">303 +</span><span class="lnt">304 +</span><span class="lnt">305 +</span><span class="lnt">306 +</span><span class="lnt">307 +</span><span class="lnt">308 +</span><span class="lnt">309 +</span><span class="lnt">310 +</span><span class="lnt">311 +</span><span class="lnt">312 +</span><span class="lnt">313 +</span><span class="lnt">314 +</span><span class="lnt">315 +</span><span class="lnt">316 +</span><span class="lnt">317 +</span><span class="lnt">318 +</span><span class="lnt">319 +</span><span class="lnt">320 +</span><span class="lnt">321 +</span><span class="lnt">322 +</span><span class="lnt">323 +</span><span class="lnt">324 +</span><span class="lnt">325 +</span><span class="lnt">326 +</span><span class="lnt">327 +</span><span class="lnt">328 +</span><span class="lnt">329 +</span><span class="lnt">330 +</span><span class="lnt">331 +</span><span class="lnt">332 +</span><span class="lnt">333 +</span><span class="lnt">334 +</span><span class="lnt">335 +</span><span class="lnt">336 +</span><span class="lnt">337 +</span><span class="lnt">338 +</span><span class="lnt">339 +</span><span class="lnt">340 +</span><span class="lnt">341 +</span><span class="lnt">342 +</span><span class="lnt">343 +</span><span class="lnt">344 +</span><span class="lnt">345 +</span><span class="lnt">346 +</span><span class="lnt">347 +</span><span class="lnt">348 +</span><span class="lnt">349 +</span><span class="lnt">350 +</span><span class="lnt">351 +</span><span class="lnt">352 +</span><span class="lnt">353 +</span><span class="lnt">354 +</span><span class="lnt">355 +</span><span class="lnt">356 +</span><span class="lnt">357 +</span><span class="lnt">358 +</span><span class="lnt">359 +</span><span class="lnt">360 +</span><span class="lnt">361 +</span><span class="lnt">362 +</span><span class="lnt">363 +</span><span class="lnt">364 +</span><span class="lnt">365 +</span><span class="lnt">366 +</span><span class="lnt">367 +</span><span class="lnt">368 +</span><span class="lnt">369 +</span><span class="lnt">370 +</span><span class="lnt">371 +</span><span class="lnt">372 +</span><span class="lnt">373 +</span><span class="lnt">374 +</span><span class="lnt">375 +</span><span class="lnt">376 +</span><span class="lnt">377 +</span><span class="lnt">378 +</span><span class="lnt">379 +</span><span class="lnt">380 +</span><span class="lnt">381 +</span><span class="lnt">382 +</span><span class="lnt">383 +</span><span class="lnt">384 +</span><span class="lnt">385 +</span><span class="lnt">386 +</span><span class="lnt">387 +</span><span class="lnt">388 +</span><span class="lnt">389 +</span><span class="lnt">390 +</span><span class="lnt">391 +</span><span class="lnt">392 +</span><span class="lnt">393 +</span><span class="lnt">394 +</span><span class="lnt">395 +</span><span class="lnt">396 +</span><span class="lnt">397 +</span><span class="lnt">398 +</span><span class="lnt">399 +</span><span class="lnt">400 +</span><span class="lnt">401 +</span><span class="lnt">402 +</span><span class="lnt">403 +</span><span class="lnt">404 +</span><span class="lnt">405 +</span><span class="lnt">406 +</span><span class="lnt">407 +</span><span class="lnt">408 +</span><span class="lnt">409 +</span><span class="lnt">410 +</span><span class="lnt">411 +</span><span class="lnt">412 +</span><span class="lnt">413 +</span><span class="lnt">414 +</span><span class="lnt">415 +</span><span class="lnt">416 +</span><span class="lnt">417 +</span><span class="lnt">418 +</span><span class="lnt">419 +</span><span class="lnt">420 +</span><span class="lnt">421 +</span><span class="lnt">422 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/* +</span></span><span class="line"><span class="cl"> * Copyright <span class="o">(</span>c<span class="o">)</span> 2006-2023, RT-Thread Development Team +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * SPDX-License-Identifier: Apache-2.0 +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * Change Logs: +</span></span><span class="line"><span class="cl"> * Date Author Notes +</span></span><span class="line"><span class="cl"> * 2023-10-28 Wangyuqiang first version +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Arduino.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;SPI.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Wire.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_GFX.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_SSD1306.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_WIDTH 128 // OLED display width, in pixels</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_HEIGHT 64 // OLED display height, in pixels</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// Declaration <span class="k">for</span> an SSD1306 display connected to I2C <span class="o">(</span>SDA, SCL pins<span class="o">)</span> +</span></span><span class="line"><span class="cl">// The pins <span class="k">for</span> I2C are defined by the Wire-library. +</span></span><span class="line"><span class="cl">// On an arduino UNO: A4<span class="o">(</span>SDA<span class="o">)</span>, A5<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino MEGA 2560: 20<span class="o">(</span>SDA<span class="o">)</span>, 21<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino LEONARDO: 2<span class="o">(</span>SDA<span class="o">)</span>, 3<span class="o">(</span>SCL<span class="o">)</span>, ... +</span></span><span class="line"><span class="cl"><span class="c1">#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_ADDRESS 0x3C ///&lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32</span> +</span></span><span class="line"><span class="cl">Adafruit_SSD1306 display<span class="o">(</span>SCREEN_WIDTH, SCREEN_HEIGHT, <span class="p">&amp;</span>Wire, OLED_RESET<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define NUMFLAKES 10 // Number of snowflakes in the animation example</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_HEIGHT 16</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_WIDTH 16</span> +</span></span><span class="line"><span class="cl">static const unsigned char PROGMEM logo_bmp<span class="o">[]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="o">{</span> 0b00000000, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11110011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11111110, 0b11111000, +</span></span><span class="line"><span class="cl"> 0b01111110, 0b11111111, +</span></span><span class="line"><span class="cl"> 0b00110011, 0b10011111, +</span></span><span class="line"><span class="cl"> 0b00011111, 0b11111100, +</span></span><span class="line"><span class="cl"> 0b00001101, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00011011, 0b10100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01111100, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01110000, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00000000, 0b00110000 <span class="o">}</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void setup<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.begin<span class="o">(</span>115200<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // <span class="nv">SSD1306_SWITCHCAPVCC</span> <span class="o">=</span> generate display voltage from 3.3V internally +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span>!display.begin<span class="o">(</span>SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS<span class="o">))</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;SSD1306 allocation failed&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span><span class="p">;</span> // Don<span class="s1">&#39;t proceed, loop forever +</span></span></span><span class="line"><span class="cl"><span class="s1"> } +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show initial display buffer contents on the screen -- +</span></span></span><span class="line"><span class="cl"><span class="s1"> // the library initializes this with an Adafruit splash screen. +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); // Pause for 2 seconds +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Clear the buffer +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.clearDisplay(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Draw a single pixel in white +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.drawPixel(10, 10, SSD1306_WHITE); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show the display buffer on the screen. You MUST call display() after +</span></span></span><span class="line"><span class="cl"><span class="s1"> // drawing commands to make them visible on screen! +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); +</span></span></span><span class="line"><span class="cl"><span class="s1"> // display.display() is NOT necessary after every single drawing command, +</span></span></span><span class="line"><span class="cl"><span class="s1"> // unless that&#39;</span>s what you want...rather, you can batch up a bunch of +</span></span><span class="line"><span class="cl"> // drawing operations and <span class="k">then</span> update the screen all at once by calling +</span></span><span class="line"><span class="cl"> // display.display<span class="o">()</span>. These examples demonstrate both approaches... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawtriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfilltriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawchar<span class="o">()</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawstyles<span class="o">()</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testscrolltext<span class="o">()</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawbitmap<span class="o">()</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Invert and restore display, pausing in-between +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">false</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testanimate<span class="o">(</span>logo_bmp, LOGO_WIDTH, LOGO_HEIGHT<span class="o">)</span><span class="p">;</span> // Animate bitmaps +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void loop<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int16_t i<span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn line +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.width<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> <span class="m">2</span> seconds +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so rectangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-i*2, display.height<span class="o">()</span>-i*2, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawCircle<span class="o">(</span>display.width<span class="o">()</span>/2, display.height<span class="o">()</span>/2, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so circles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillCircle<span class="o">(</span>display.width<span class="o">()</span> / 2, display.height<span class="o">()</span> / 2, i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn circle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so round-rects alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so triangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0, 0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.cp437<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> // Use full <span class="m">256</span> char <span class="s1">&#39;Code Page 437&#39;</span> font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Not all the characters will fit on the display. This is normal. +</span></span><span class="line"><span class="cl"> // Library will draw what it can and the rest will be clipped. +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;256<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span><span class="nv">i</span> <span class="o">==</span> <span class="s1">&#39;\n&#39;</span><span class="o">)</span> display.write<span class="o">(</span><span class="s1">&#39; &#39;</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> display.write<span class="o">(</span>i<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0,0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_BLACK, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;inverse&#39;</span> text +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>3.141592<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;0x&#34;</span><span class="o">))</span><span class="p">;</span> display.println<span class="o">(</span>0xDEADBEEF, HEX<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>10, 0<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;scroll&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show initial text +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>100<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Scroll in various directions, pausing in-between: +</span></span><span class="line"><span class="cl"> display.startscrollright<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrollleft<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagright<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagleft<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span> +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.width<span class="o">()</span> - LOGO_WIDTH <span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.height<span class="o">()</span> - LOGO_HEIGHT<span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define XPOS 0 // Indexes into the &#39;icons&#39; array in function below</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define YPOS 1</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define DELTAY 2</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int8_t f, icons<span class="o">[</span>NUMFLAKES<span class="o">][</span>3<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Initialize <span class="s1">&#39;snowflake&#39;</span> positions +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;x: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; y: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; dy: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span> <span class="o">{</span> // Loop forever... +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear the display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Draw each snowflake: +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, bitmap, w, h, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show the display buffer on the screen +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>200<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> 1/10 second +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Then update coordinates of each flake... +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> +<span class="o">=</span> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> // If snowflake is off the bottom of the screen... +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> &gt;<span class="o">=</span> display.height<span class="o">())</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // Reinitialize to a random position, just off the top +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在此示例中有几点注意事项:</p> +<ul> +<li>在每一份添加的示例工程中,我们都必须要包含头文件 <code>#include &lt;Arduino.h&gt;</code></li> +<li>由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 <code>0x3c</code>,所以对应示例工程中的 <code>SCREEN_ADDRESS</code>需要修改为 <code>0X3C</code></li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061.png" +width="533" +height="143" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190157061" +class="gallery-image" +data-flex-grow="372" +data-flex-basis="894px" +></p> +<ul> +<li>由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍</li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190348607" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:</p> +<table> +<thead> +<tr> +<th style="text-align:center">pin</th> +<th style="text-align:center">func</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">P203</td> +<td style="text-align:center">i2c0-sda</td> +</tr> +<tr> +<td style="text-align:center">P202</td> +<td style="text-align:center">i2c0-scl</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">vcc</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">gnd</td> +</tr> +</tbody> +</table> +<p>接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695.png" +width="813" +height="431" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123191534695" +class="gallery-image" +data-flex-grow="188" +data-flex-basis="452px" +></p> +<p>查看demo:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo.gif" +width="1280" +height="720" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif 1024w" +loading="lazy" +alt="demo" +class="gallery-image" +data-flex-grow="177" +data-flex-basis="426px" +></p>【经验分享】如何让你的终端实现自动补齐、历史回溯https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/cover.jpg" alt="Featured image of post 【经验分享】如何让你的终端实现自动补齐、历史回溯" /><h2 id="linux下配置">Linux下配置 +</h2><p>在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:</p> +<h3 id="步骤-1-安装-zsh">步骤 1: 安装 zsh +</h3><p>确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install zsh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-2-安装-oh-my-zsh">步骤 2: 安装 oh-my-zsh +</h3><p>在终端中运行以下命令来安装 oh-my-zsh:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者,如果你没有安装 <code>curl</code>,可以使用 <code>wget</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-3-更改主题">步骤 3: 更改主题 +</h3><ol> +<li> +<p>打开 <code>~/.zshrc</code> 文件以编辑它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nano ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>找到 <code>ZSH_THEME</code> 行并更改主题。你可以在 <a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" target="_blank" rel="noopener" +>oh-my-zsh 主题库</a>中选择一个主题,例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">ZSH_THEME</span><span class="o">=</span><span class="s2">&#34;agnoster&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>保存并关闭文件。</p> +</li> +</ol> +<h3 id="步骤-4-启用历史回溯">步骤 4: 启用历史回溯 +</h3><p>oh-my-zsh 默认启用历史回溯。确保 <code>~/.zshrc</code> 中没有明确禁用该功能的设置。检查是否存在以下行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;yyyy-mm-dd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-5-重新启动-zsh-或打开新终端">步骤 5: 重新启动 zsh 或打开新终端 +</h3><p>在更改 <code>~/.zshrc</code> 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 <code>zsh</code> 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。</p> +<h2 id="windwos下配置">Windwos下配置 +</h2><p>在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 <code>PSReadLine</code> 模块,它提供了丰富的命令行编辑和历史记录功能。</p> +<p>以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:</p> +<ol> +<li> +<p><strong>安装 PSReadLine 模块:</strong> +打开 PowerShell 终端,并执行以下命令来安装 <code>PSReadLine</code> 模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">PSReadLine</span> <span class="n">-Force</span> <span class="n">-SkipPublisherCheck</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>配置 PowerShell 用户配置文件:</strong> +执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">notepad</span> <span class="nv">$PROFILE</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>在配置文件中添加以下行:</strong> +在打开的配置文件中,添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Import-Module</span> <span class="n">PSReadLine</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-HistoryNoDuplicates:</span><span class="vm">$false</span> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-EditMode</span> <span class="n">Emacs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存并关闭文件。</p> +</li> +<li> +<p><strong>重新启动 PowerShell:</strong> +关闭当前的 PowerShell 终端,并重新打开一个新的终端。</p> +</li> +<li> +<p><strong>使用历史记录搜索:</strong> +可以在 PowerShell 终端中使用 <code>Ctrl + r</code> 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。</p> +</li> +</ol>【嵌入式素养提升】MPU与MCUhttps://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/<img src="https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover.jpg" alt="Featured image of post 【嵌入式素养提升】MPU与MCU" /><h2 id="mpu与mcu">MPU与MCU +</h2><p>MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。</p> +<p>但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。</p> +<p>在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。</p> +<p>由于主要完成“控制”相关的任务,所以称为 <code>Controller</code>。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。</p> +<p>而<code>Processor</code>,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。</p> +<p>以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。</p> +<p>为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。</p> +<p>从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。</p> +<p>总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。</p>【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul>【经验分享】WSL中使用USB设备https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【经验分享】WSL中使用USB设备" /><h2 id="具体步骤">具体步骤: +</h2><p>首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:</p> +<blockquote> +<p>下载链接:https://github.com/dorssel/usbipd-win/releases</p> +</blockquote> +<p>同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开wsl ubuntu终端使用命令:<code>uname -r</code>得到版本号,同时根据版本号使用管理员模式新建目录</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7.png" +width="587" +height="103" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="569" +data-flex-basis="1367px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases</p> +<p>这里的版本就是你使用命令 <code>uname -r</code> 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下</p> +<p>然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl">$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ <span class="o">&amp;&amp;</span> sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后将内核的一些配置信息复制到当前文件夹下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp /proc/config.gz config.gz +</span></span><span class="line"><span class="cl">$ sudo gunzip config.gz +</span></span><span class="line"><span class="cl">$ sudo mv config .config +</span></span></code></pre></td></tr></table> +</div> +</div><p>接着我们执行menuconfig命令打开图形化菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入如下路径:<code>&gt; Device Drivers &gt; USB support</code></p> +<p>下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Device Drivers -&gt; USB Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB announce new devices +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB Modem <span class="o">(</span>CDC ACM<span class="o">)</span> support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; VHCI HCD +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support -&gt; USB FTDI Single port Serial Driver +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时记得关闭 <code>Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; Debug messages for USB/IP</code>这一选项,否则调试信息会非常影响你的使用体验</p> +<p>另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>内核编译期间发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" +width="1069" +height="344" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="310" +data-flex-basis="745px" +></p> +<p>这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install dwarves +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo make -j8 <span class="o">&amp;&amp;</span> sudo make modules_install -j8 <span class="o">&amp;&amp;</span> sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现又产生了报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac.png" +width="932" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="300" +data-flex-basis="721px" +></p> +<p>查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo vi .config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装内核时发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png.webp" +width="1200" +height="176" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="681" +data-flex-basis="1636px" +></p> +<p>解决方式有两种:</p> +<ul> +<li>1.可以选择在<code>.config</code>中禁用宏<code>CONFIG_X86_X32</code></li> +<li>2.找到合适的binutils版本使其能够编译</li> +</ul> +<p>我选择的是第一种,根据我在网上找到的说法是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>所以我选择禁用宏<code>CONFIG_X86_X32</code>,之后继续执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make modules_install -j8 +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>之后就可以选择编译 USBIP 工具了:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> tools/usb/usbip +</span></span><span class="line"><span class="cl">$ sudo ./autogen.sh +</span></span><span class="line"><span class="cl">$ sudo ./configure +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>复制工具库位置,以便 usbip 工具可以获取到:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装 usb.ids 以便显示 USB 设备的名称:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt-get install hwdata +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启WSL:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ wsl --shutdown +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面进行测试是否成功: +打开powershell:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl list +</span></span></code></pre></td></tr></table> +</div> +</div><p>假设我们需要在wsl使用的 usb 设备为 <code>ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3)</code>,设备id为 <code>0483:374b</code></p> +<p>我们使用命令附加设备到 wsl2 中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;0483:374b&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" +width="1200" +height="408" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="294" +data-flex-basis="705px" +></p> +<p>此时我们打开一个 wsl 终端,使用命令 <code>lsusb</code> 即可看到附加到 wsl 的设备</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96.png" +width="1146" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="369" +data-flex-basis="887px" +></p> +<p>然后我们再次回到 powershell ,执行 <code>usbipd wsl list</code>命令,可以看到此时的 usb 设备已经成功添加到 wsl 了</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" +width="1200" +height="572" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="209" +data-flex-basis="503px" +></p>【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Linux系统开发】Linux常见开发汇总https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover.jpg" alt="Featured image of post 【Linux系统开发】Linux常见开发汇总" /><h2 id="1vmware-tools-灰色无法点击">1.vmware tools 灰色无法点击 +</h2><p>执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get update +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get upgrade +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install open-vm-tools-desktop -y +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2linux安装搜狗输入法">2.linux安装搜狗输入法 +</h2><p>终端安装 fcitx</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install fcitx +</span></span></code></pre></td></tr></table> +</div> +</div><p>到搜狗官方下载 deb 包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://shurufa.sogou.com/linux" target="_blank" rel="noopener" +>https://shurufa.sogou.com/linux</a></li> +</ul> +</blockquote> +<p>使用linux自带的安装程序安装输入法后,安装如下输入法依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 +</span></span><span class="line"><span class="cl">sudo apt install libgsettings-qt1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启即可</p> +<h2 id="3cmake安装指定版本">3.Cmake安装指定版本 +</h2><p>首先去官网下载所需版本的压缩包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://cmake.org/files/" target="_blank" rel="noopener" +>https://cmake.org/files/</a></li> +</ul> +</blockquote> +<p>执行解压命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -zxv -f cmake-3.22.6.tar.gz +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装相关依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install g++ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install make +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入解压后的cmake文件,执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./bootstrap +</span></span></code></pre></td></tr></table> +</div> +</div><p>编译构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">make +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo make install +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4ubuntu中使用-st-link">4.ubuntu中使用 st-link +</h2><p>安装依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc +</span></span></code></pre></td></tr></table> +</div> +</div><p>依次执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># download source code</span> +</span></span><span class="line"><span class="cl">git clone https://github.com/stlink-org/stlink +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> stlink +</span></span><span class="line"><span class="cl"><span class="c1"># build</span> +</span></span><span class="line"><span class="cl">cmake . +</span></span><span class="line"><span class="cl">make +</span></span><span class="line"><span class="cl"><span class="c1"># install</span> +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bin +</span></span><span class="line"><span class="cl">sudo cp st-* /usr/local/bin +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ../lib +</span></span><span class="line"><span class="cl">sudo cp *.so* /lib32 +</span></span><span class="line"><span class="cl"><span class="c1"># add rules</span> +</span></span><span class="line"><span class="cl">sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ +</span></span><span class="line"><span class="cl">sudo udevadm control --reload-rules +</span></span><span class="line"><span class="cl">sudo udevadm trigger +</span></span></code></pre></td></tr></table> +</div> +</div><p>尝试烧录代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#check if st-link is plugged</span> +</span></span><span class="line"><span class="cl">sudo st-info --probe +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># write hex</span> +</span></span><span class="line"><span class="cl">sudo st-flash --format ihex write myapp.hex +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 一般下载一次,会失败,需要刷入两次;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># write bin</span> +</span></span><span class="line"><span class="cl">sudo st-flash write in.bin 0x8000000 <span class="c1">#stm32f4xx</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># read bin</span> +</span></span><span class="line"><span class="cl">st-flash <span class="nb">read</span> out.bin 0x8000000 0x1000 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># restart</span> +</span></span><span class="line"><span class="cl"><span class="c1"># 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作</span> +</span></span><span class="line"><span class="cl">sudo st-flash reset +</span></span></code></pre></td></tr></table> +</div> +</div><p>具体的GDB调试可以参考这篇文章:</p> +<blockquote> +<ul> +<li><a class="link" href="https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html" target="_blank" rel="noopener" +>https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html</a></li> +</ul> +</blockquote>【Git版本控制】Github和Gitlab同时使用sshhttps://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover.jpg" alt="Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh" /><h2 id="前言">前言 +</h2><p>最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下</p> +<h2 id="本地生成公私密钥">本地生成公私密钥 +</h2><p>首先确保把之前的 ssh 信息清除,也可以将整个 <code>~/.ssh</code> 目录删除</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rm -rf ~/.ssh/* +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们分别生成 Github 和 Gitlab账号的 SSH 密钥</p> +<ul> +<li>Github 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意不要选择其他操作,一路回车即可</p> +<p>此时打开 <code>~/.ssh/</code> 目录可以看到生成了四个文件:<code>github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub</code></p> +<p>其中 <code>.pub</code> 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存</p> +<h2 id="远程仓库-ssh-填写公钥密钥">远程仓库 SSH 填写公钥密钥 +</h2><p>我们先打开 Github 的 Settings选项,然后选择 <code>SSH and GPG keys-&gt;New SSH key</code> ,<code>Title</code>可以随意拟定,<code>Key</code>需要查看刚刚的 <code>github_id-rsa.pub</code> 文件,并且复制到 Gitlab 的<code>key</code>一栏中;</p> +<p>Gitlab 的操作方式与 Github 类似,具体步骤:</p> +<p>打开 <code>Gitlab -&gt; 用户设置 -&gt; SSH密钥</code> ,在密钥一栏填入 <code>gitlab_id-rsa.pub</code>文件中的具体值,标题自拟即可。</p> +<h2 id="配置不同-host-的-ssh-key">配置不同 Host 的 SSH Key +</h2><p>回到 <code>~/.ssh/</code> 目录下,并且创建一个名为 <code>config</code> 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#github</span> +</span></span><span class="line"><span class="cl">Host github.com +</span></span><span class="line"><span class="cl"> Hostname ssh.github.com +</span></span><span class="line"><span class="cl"> Port <span class="m">443</span> +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/github_id-rsa +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#gitlab</span> +</span></span><span class="line"><span class="cl">host git.rt-thread.com +</span></span><span class="line"><span class="cl"> Hostname git.rt-thread.com +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/figure/ssh-config.png" +loading="lazy" +></p> +<h2 id="验证">验证 +</h2><p>使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置</p> +<ul> +<li>Github SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@github.com +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@rt-thread.com +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功</p> +<p><img src="https://kurisaw.github.io/figure/valid-ssh.png" +loading="lazy" +></p>【Matter】CHIP设备层设计笔记https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/<img src="https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover.jpg" alt="Featured image of post 【Matter】CHIP设备层设计笔记" /><h1 id="chip设备层设计笔记">CHIP设备层设计笔记 +</h1><p>本文档包含与 CHIP 设备层 ( <code>src/platform</code>) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。</p> +<p>这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。</p> +<p>本文档包含以下部分:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Device-Layer-Adaptation-Patterns" target="_blank" rel="noopener" +>设备层适配模式</a></li> +</ul> +<hr> +<h3 id="设备层适配模式">设备层适配模式 +</h3><p>设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。</p> +<p>CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。</p> +<p>作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。</p> +<p>为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。</p> +<p>尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。</p> +<p>以下各节描述了用于实现这些目标的一些模式。</p> +<ol> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Interface-and-Implementation-Classes" target="_blank" rel="noopener" +>接口和实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Method-Forwarding" target="_blank" rel="noopener" +>方法转发</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Target-Platform-Selection" target="_blank" rel="noopener" +>目标平台选择</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Generic-Implementation-Classes" target="_blank" rel="noopener" +>通用实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Overriding-Generic-Behaviors" target="_blank" rel="noopener" +>覆盖通用行为</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Multiple-Inheritance-and-Subclassing-of-Generic-Implementations" target="_blank" rel="noopener" +>通用实现的多重继承和子类化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Static-Virtualization-of-Generic-Implementation-Behavior" target="_blank" rel="noopener" +>通用实现行为的静态虚拟化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#-ipp-files-and-explicit-template-instantiation" target="_blank" rel="noopener" +>.cpp 文件和显式模板实例化</a></li> +</ol> +<hr> +<h3 id="接口和实现类">接口和实现类 +</h3><p>CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。</p> +<p>外部可见的<em><strong>抽象接口类</strong></em>定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。</p> +<p>实现<em><strong>类</strong></em>提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。</p> +<p>设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。</p> +<p>抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀<code>Impl</code>。在所有情况下,实现类都需要从其接口类公开继承。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for a specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="方法转发">方法转发 +</h3><p>接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。<code>this</code>这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪的重复模板模式</a> ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,<code>ImplClass</code>使转发方法定义更加简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* forward method call... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>作为转发方法目标的实现类上的方法称为*<strong>实现方法*</strong>。每一种转发方法都必须有相应的实现方法。</p> +<p>前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。</p> +<p>实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Let the forwarding methods on ConfigurationManager call implementation +</span></span><span class="line"><span class="cl"> methods on this class. */ +</span></span><span class="line"><span class="cl"> friend ConfigurationManager; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">private: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR _Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding implementation method... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding static implementation method... */ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="目标平台选择">目标平台选择 +</h3><p>实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of ConfigurationManager.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#define CONFIGURATIONMANAGERIMPL_HEADER \ +</span></span><span class="line"><span class="cl"> &lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h&gt; +</span></span><span class="line"><span class="cl">#include CONFIGURATIONMANAGERIMPL_HEADER +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span></code></pre></td></tr></table> +</div> +</div><p>该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。</p> +<p>每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如<code>ESP32</code>)。所有此类文件都具有相同的文件名(例如<code>ConfigurationManagerImpl.h</code>),并且每个文件都包含类似名称的类的定义(<code>ConfigurationManagerImpl</code>)。</p> +<p>特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 <code>src/adaptations/device-layer/ESP32</code>)。与特定于平台的头目录一样,这些子目录以目标平台命名。</p> +<p>设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 <code>--device-layer=&lt;target-platform&gt;</code>。传递 &ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET ESP32 +</span></span><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET_ESP32 1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>&ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。</p> +<h3 id="通用实现类">通用实现类 +</h3><p>通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。</p> +<p>为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。</p> +<p>通用实现基类被实现为遵循 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪重复模板模式的</a>C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Implementation provided by +</span></span><span class="line"><span class="cl"> generic base class. */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); /* &lt;-- Invoked when GetDeviceId() called. */ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="覆盖通用行为">覆盖通用行为 +</h3><p>如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。</p> +<p>新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using GenericImpl = GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Call the generic implementation to get the device id. */ +</span></span><span class="line"><span class="cl"> uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Special case the situation where the device id is not known. */ +</span></span><span class="line"><span class="cl"> if (deviceId == kNodeIdNotSpecified) { +</span></span><span class="line"><span class="cl"> deviceId = PLATFORM_DEFAULT_DEVICE_ID; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return deviceId; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现的多重继承和子类化">通用实现的多重继承和子类化 +</h3><p>具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericWiFiConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;, /* &lt;-- WiFi features */ +</span></span><span class="line"><span class="cl"> public GenericThreadConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Thread features */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on all platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on FreeRTOS platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl_FreeRTOS +</span></span><span class="line"><span class="cl"> : public GenericPlatformManagerImpl&lt;ImplClass&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现行为的静态虚拟化">通用实现行为的静态虚拟化 +</h3><p>在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。</p> +<p>例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过<code>GetDeviceId()</code>从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。</p> +<p><code>this</code>遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数<code>Impl()</code>有助于使代码简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericConfigurationManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ConfigurationManagerImpl</span> <span class="n">final</span> +</span></span><span class="line"><span class="cl"> <span class="p">:</span> <span class="n">public</span> <span class="n">ConfigurationManager</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">public</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">friend</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">delegate</span> <span class="n">to</span> <span class="n">the</span> <span class="n">implementation</span> <span class="k">class</span> <span class="n">to</span> <span class="n">read</span> <span class="n">the</span> <span class="s1">&#39;device-id&#39;</span> <span class="n">config</span> <span class="n">value</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="err">“</span><span class="n">device</span><span class="o">-</span><span class="n">id</span><span class="err">”</span><span class="p">,</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">ConfigurationManagerImpl</span><span class="p">::</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">read</span> <span class="n">value</span> <span class="n">from</span> <span class="n">platform</span><span class="o">-</span><span class="n">specific</span> <span class="n">key</span><span class="o">-</span><span class="n">value</span> <span class="n">store</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。</p> +<p>同样,委托是通过转换<code>this</code>指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericPlatformManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">Delegate</span> <span class="n">work</span> <span class="n">to</span> <span class="n">method</span> <span class="n">that</span> <span class="n">can</span> <span class="n">be</span> <span class="n">overridden</span> <span class="n">by</span> <span class="n">implementation</span> <span class="k">class</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">provide</span> <span class="n">default</span> <span class="n">implementation</span> <span class="n">of</span> <span class="n">DispatchEventToApplication</span><span class="p">()</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="cpp-文件和显式模板实例化">.cpp 文件和显式模板实例化 +</h3><p>C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。</p> +<p>为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀<code>.cpp</code>。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.cpp */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">CHIP_ERROR GenericConfigurationManagerImpl&lt;ImplClass&gt;::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。<a class="link" href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation" target="_blank" rel="noopener" +>为了避免这种情况,设备层使用显式模板实例化</a>的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件<code>extern template class</code>在使用模板类之前都包含一个声明。这告诉编译器<em>不要</em>在该上下文中实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.h */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Instruct the compiler to instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span></span><span class="line"><span class="cl"><span class="c1">// class only when explicitly asked to do so. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">extern</span> <span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并<code>template class</code>使用定义来强制显式实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.cpp */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Fully instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; class. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。</p>【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)" /><h1 id="如何在linux平台下测试matter应用级通信虚拟设备">如何在Linux平台下测试Matter应用级通信(虚拟设备) +</h1><hr> +<h2 id="准备工作">准备工作 +</h2><h3 id="1-递归克隆matter仓库">1. 递归克隆Matter仓库 +</h3><p>执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果克隆过程中发生报错,请执行如下命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout v1.0 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2-matter依赖项安装">2. Matter依赖项安装 +</h3><p>Matter 构建依赖于以下软件包及环境库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果通过<code> build_examples.py</code> 和 <code>-with-ui</code> 变体进行构建,也要安装 SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-matter环境构建">3. Matter环境构建 +</h3><p>执行<code>scripts/activate.sh</code>脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190833624.png" +loading="lazy" +alt="image-20230619083303148" +></p> +<p>如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-安装zap">4. 安装zap +</h3><blockquote> +<p>注意:zap 包目前不可用<code>arm64</code>(比如在 Raspberry PI 上编译时)。</p> +</blockquote> +<ul> +<li>**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node -v +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果安装的话不出意外会出现版本号。</p> +<ul> +<li><strong>Step2:zap安装</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> connectedhomeip/scripts/tools/zap +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">python3 zap_download.py +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是安装日志:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip +</span></span><span class="line"><span class="cl">2023-06-19 13:29:20 root INFO Data downloaded, extracting ... +</span></span><span class="line"><span class="cl">2023-06-19 13:29:25 root INFO Done extracting. +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_INSTALL_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step3:配置zap环境变量</strong></li> +</ul> +<p>我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为<code>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly</code>,在此目录下有个 zap 脚本,我们这个位置一定要记住!!</p> +<p>设置<code>ZAP_DEVELOPMENT_PATH</code>环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step4:运行zap引导程序</strong></li> +</ul> +<p>执行如下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./run_zaptool.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>效果如下:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191346155.png" +loading="lazy" +alt="image-20230619134658521" +></p> +<ul> +<li><strong>Step4:为了方便我们后续使用zap,我们设置root终端下自启动:</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">vi ~/.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>.bashrc</code>文件最末添加如下代码,也就是配置zap环境变量</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出!</p> +<h2 id="应用程序构建">应用程序构建 +</h2><p>在官方文档中提供有两种构建方式:</p> +<ul> +<li>通过脚本构建</li> +<li>使用 Gn 和 Ninja 命令构建</li> +</ul> +<h3 id="1-通过脚本构建">1. 通过脚本构建 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build_script.sh EXAMPLE_DIR OUTPUT_DIR <span class="o">[</span>ARGUMENTS<span class="o">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>build_script.sh</code> 是脚本的文件名;</li> +<li><code>EXAMPLE_DIR</code> 是示例项目的目录路径;</li> +<li><code>OUTPUT_DIR</code> 是构建输出的目录路径;</li> +<li><code>[ARGUMENTS]</code> 是可选的其他参数,用于设置gn和ninja命令的选项。</li> +</ul> +<h4 id="11-构建示例">1.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ <span class="nv">chip_tests_zap_config</span><span class="o">=</span><span class="se">\&#34;</span>app1<span class="se">\&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190835972.png" +loading="lazy" +alt="image-20230619083551820" +></p> +<h4 id="12-运行构建">1.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./out/simulated/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190843752.png" +loading="lazy" +alt="image-20230619084309631" +></p> +<h3 id="2-通过-gn-和-ninja-构建应用程序">2. 通过 gn 和 ninja 构建应用程序 +</h3><h4 id="21-构建示例">2.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span><span class="line"><span class="cl">gn gen --check --root<span class="o">=</span>examples/placeholder/linux out/simulated --args<span class="o">=</span><span class="s2">&#34;chip_tests_zap_config=\&#34;app1\&#34;&#34;</span> +</span></span><span class="line"><span class="cl">ninja -C out/simulated +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22-运行构建">2.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./out/app1/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191510937.png" +loading="lazy" +alt="image-20230619151054483" +></p> +<h2 id="测试应用程序">测试应用程序 +</h2><p>在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191513515.png" +loading="lazy" +alt="image-20230619151353417" +></p> +<p>我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> out/debug +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./chip-tool onoff on 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff off 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> accepted-command-list 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> on-time 0x654321 <span class="m">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191530858.png" +loading="lazy" +alt="image-20230619153015727" +></p> +<p>具体更多的使用命令可参考:<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md" target="_blank" rel="noopener" +>Chip tool</a></p> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/simulated_device_linux.md" target="_blank" rel="noopener" +>simulated_device_linux</a></li> +<li><a class="link" href="https://github.com/project-chip/zap" target="_blank" rel="noopener" +>zap</a></li> +</ul>【Matter】Matter学习笔记1https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/<img src="https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover.jpg" alt="Featured image of post 【Matter】Matter学习笔记1" /><h1 id="matter学习笔记1">Matter学习笔记1 +</h1><hr> +<p>在了解Matter之前,可以选择先了解以下前提知识:</p> +<ul> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118389957" target="_blank" rel="noopener" +>matter网络基础之—Thread</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118553988" target="_blank" rel="noopener" +>matter网络基础之—Wi-Fi</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/119253287" target="_blank" rel="noopener" +>边界路由器,网关和Wi-Fi接入点</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/120067170" target="_blank" rel="noopener" +>Thread地址(IPv6 and RLOC16)</a></li> +</ul> +<blockquote> +<p>以上资料来自CSDN博主:<a class="link" href="https://blog.csdn.net/qq_42860989" target="_blank" rel="noopener" +>Eagle115</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。</p> +<p>Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个<strong>统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准</strong>。</p> +<p>Matter 作为一个<strong>应用级的协议</strong>,向下屏蔽了<strong>设备制造商的生态和系统,让各种智能家居设备之间能相互通信</strong>。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。</p> +<p>Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:</p> +<ul> +<li><strong>低功耗蓝牙技术</strong>:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。</li> +<li><strong>二维码进行配置</strong>:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。</li> +<li><strong>Wi-Fi 技术进行高速数据传输</strong>:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。</li> +<li><strong>Thread 协议进行低速数据传输</strong>:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。</li> +</ul> +<h2 id="matter协议架构">Matter协议架构 +</h2><h3 id="1matter-over-ipv6">1.Matter Over IPV6 +</h3><p>该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。</p> +<p>IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。</p> +<p>下面是IPV4 和 IPV6 的一些区别:</p> +<table> +<thead> +<tr> +<th style="text-align:center">区别</th> +<th style="text-align:center">IPV4</th> +<th style="text-align:center">IPV6</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">地址长度</td> +<td style="text-align:center">32 bits</td> +<td style="text-align:center">128 bits</td> +</tr> +<tr> +<td style="text-align:center">地址数量</td> +<td style="text-align:center">约<strong>4x10^9</strong></td> +<td style="text-align:center">约<strong>3.4×10^38</strong></td> +</tr> +<tr> +<td style="text-align:center">地址类型</td> +<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> +<td style="text-align:center">通过 DHCPv6 动态分配</td> +</tr> +<tr> +<td style="text-align:center">安全性</td> +<td style="text-align:center">IPsec(Internet协议安全标准) 为可选项</td> +<td style="text-align:center">IPsec 为默认选项</td> +</tr> +<tr> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +</tr> +</tbody> +</table> +<h3 id="2matter协议架构">2.Matter协议架构 +</h3><p>Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121952614.png" +loading="lazy" +></p> +<p>为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此<strong>天生具备IP连接能力</strong>,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;</p> +<p>Matter 还支持<strong>桥接</strong>等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行<strong>Bridge</strong>;</p> +<p>由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!</p> +<h3 id="3matter标准协议架构">3.Matter标准协议架构 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121138795.png" +loading="lazy" +></p> +<p><strong>Matter标准协议架构总体流程分析:</strong></p> +<p>首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议<a class="link" href="" >Message Reliability Protocol</a>);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。</p> +<p>后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!</p> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p>原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。</p> +<p>在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。</p> +<p>Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为<strong>Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层</strong>。而 <strong>6LoWPAN协议</strong> 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。</p> +<p>因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。</p> +<h3 id="mesh组网">Mesh组网 +</h3><p>在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。</p> +<p>目前最流行的全屋WiFi方案主要有两种:<strong>Mesh路由器组网</strong>和<strong>AC+AP</strong>两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。</p> +<p>无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,<strong>无线Mesh网络</strong>中的<strong>AP</strong>可以采用<strong>无线连接</strong>的方式进行互连,并且<strong>AP间可以建立多跳的无线链路</strong>。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +loading="lazy" +alt="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +></p> +<p>这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:</p> +<h3 id="1单一网络拓扑">1.单一网络拓扑 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121601076.png" +loading="lazy" +></p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121516744.png" +loading="lazy" +></p> +<p>在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是<strong>Thread/802.15.4网络</strong>、<strong>Wi-Fi网络</strong>或<strong>以太网网络</strong>。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,<strong>前提是所有段都在链路层桥接</strong>。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。</p> +<p>在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。</p> +<p>在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为<strong>Fabric</strong>。</p> +<blockquote> +<p>注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。</p> +</blockquote> +<h3 id="2星形网络拓扑">2.星形网络拓扑 +</h3><ul> +<li><strong>AP(Access Point)</strong>:WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。</li> +<li><strong>STA(Station)</strong>:STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。</li> +<li><strong>BR(Border Router)</strong>:指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。</li> +<li><strong>ED(End device)</strong>:指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +<li><strong>R(Router)</strong>:指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。</li> +<li><strong>SED(Sleepy End Device)</strong>:指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121605090.png" +loading="lazy" +></p> +<p>星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。<strong>外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。</strong></p> +<p>在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。</p> +<p>该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。</p> +<blockquote> +<p>注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。</p> +</blockquote> +<h2 id="设备数据模型date-model">设备数据模型(Date Model) +</h2><p>在 Matter 中的设备具有明确定义的<strong>数据模型</strong> (<strong>DM</strong>),这是对设备功能的分层建模。在此层次结构的顶层,有一个<strong>Device</strong>。</p> +<h3 id="1设备和端点nodeendpoint">1.设备和端点(Node、Endpoint) +</h3><p>所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。</p> +<p>一组节点包含了多组<strong>Endpoint(端点)</strong>。<strong>而每个端点都封装了一个功能集</strong>。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122042737.png" +loading="lazy" +></p> +<h3 id="2节点角色node-roles">2.节点角色(Node roles) +</h3><p>在Matter 中,每一个物理设备都被称之为<strong>Node</strong>,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!</p> +<p><strong>Node roles</strong>是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:</p> +<ul> +<li><strong>Commissioner :执行</strong><a class="link" href="https://developers.home.google.com/matter/primer/commissioning" target="_blank" rel="noopener" +>调试</a>的节点 。</li> +<li><strong>控制器</strong>:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>开/关灯开关</a>)具有控制器角色。</li> +<li><strong>Controlee</strong> : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>On/Off Light Switch</a>。开/关灯开关只能<em>是</em>控制器。它不能是受控人。</li> +<li><strong>OTA Provider</strong> : 可以提供 OTA 软件更新的节点。</li> +<li><strong>OTA 请求者</strong>:可以请求 OTA 软件更新的节点。</li> +</ul> +<h3 id="3集群cluster">3.集群(Cluster) +</h3><p>在一个<strong>Endpoint</strong>中,一个 Node 有一个或多个<strong>Clusters</strong>。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的<em>开/关</em>集群,或可调光端点上的<em>电平控制集群。</em></p> +<p>一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。</p> +<h4 id="31-属性attributes">3.1 属性(Attributes) +</h4><p>在最后一层,我们会找到<strong>Attributes</strong>,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122111729.png" +loading="lazy" +></p> +<h4 id="32-命令commands">3.2 命令(Commands) +</h4><p>除了 Attributes 之外,Clusters 还有<strong>Commands</strong>,也就是<strong>触发 Cluster 进行某种行为的指令</strong>。它们等同于Matter远程过程调用的 DM。命令类似于<em>动词</em>,例如<em>Door Lock</em>集群上的 <em>lock door</em>。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。</p> +<h4 id="33-事件events">3.3 事件(Events) +</h4><p>最后,Clusters 也可能有<strong>Events</strong>,它<strong>可以被认为是过去状态转换的记录</strong>。虽然属性代表<strong>当前状态</strong>,但事件是<strong>过去</strong>的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122122628.png" +loading="lazy" +></p> +<p><code>Endpoint 0</code>作为<code>Utility Clusters</code><strong>保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新</strong>。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。</p> +<h3 id="4-cluster分类">4. Cluster分类 +</h3><p>cluster可以定义为<strong>工具(Utility) Cluster</strong>或<strong>应用(Application) Cluster</strong>。</p> +<h4 id="41-工具utility-cluster">4.1 工具(Utility) Cluster +</h4><p>工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。</p> +<blockquote> +<p>作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。</p> +</blockquote> +<h4 id="42-应用application-cluster">4.2 应用(Application) Cluster +</h4><p>应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。</p> +<blockquote> +<p>应用cluster示例:</p> +<ul> +<li>On/Off cluster —— client向server发送命令</li> +<li>Temperature Measurement cluster —— server向client报告数据</li> +</ul> +</blockquote> +<p>应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。</p> +<blockquote> +<p>示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。</p> +</blockquote> +<h3 id="5-clients-and-servers">5. Clients and Servers +</h3><p>Clusters 可能是<strong>Client Cluster</strong>或<strong>Server Cluster</strong>。服务器是<strong>有状态的</strong>,保存属性、事件和命令;而客户端是 <strong>无状态的</strong>,其职责是启动与远程服务器集群的<strong>交互</strong>,从而执行:</p> +<ul> +<li><strong>读取</strong>和<strong>写入</strong>其远程属性。</li> +<li><strong>读取</strong>其远程事件。</li> +<li><strong>调用</strong>其远程命令。</li> +</ul> +<p>虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有<code>controller/peripheral</code> 或 <code>leader/follower</code>关系。相反,关系是水平的:任何 Cluster 都可以是<strong>Server</strong>或<strong>Client</strong>。因此,<strong>对于不同的集群和功能,节点可能既是服务器又是客户端。</strong></p> +<p>例如,我们可能有两个台灯:<strong>节点 A</strong>和<strong>节点 B</strong>。两个节点都实现了一个<em>开/关灯</em>设备类型。此设备类型包括控制其各自物理光输出的<em>开/关服务器集群。</em></p> +<p>但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现<em>开/关客户端</em>集群,以便它可以控制服务器集群。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122240843.png" +loading="lazy" +></p> +<p>在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。</p> +<p>在下一节中,我们将详细介绍客户端和服务器集群如何交互: <strong>Interaction Model(交互模型)</strong>。</p> +<h2 id="交互模型">交互模型 +</h2><h3 id="1概念">1.概念 +</h3><p>如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。<strong>交互模型</strong>(<strong>IM</strong>),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。</p> +<p><strong>节点通过以下方式相互交互:</strong></p> +<ul> +<li>读取和订阅属性和事件</li> +<li>写入属性</li> +<li>调用命令</li> +</ul> +<p>每当一个节点与另一个节点建立加密通信序列时,它们就构成了<strong>交互</strong>关系。<strong>Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成</strong>,可以理解为 Node 之间的 IM 级消息。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306140839728.png" +loading="lazy" +></p> +<p>Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。</p> +<h4 id="11-发起者initiators-和目标targets">1.1 发起者(Initiators )和目标(Targets) +</h4><p>在Matter中,节点的发起目标被称为<strong>发起者(Initiators )</strong>,而响应的节点则作为<strong>目标(Target)</strong>。一般来说,发起者是客户端集群,而目标是客户端集群。</p> +<h4 id="12-组groups">1.2 组(Groups) +</h4><p>在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。</p> +<p>为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。</p> +<h4 id="13-路径path">1.3 路径(Path) +</h4><p><strong>当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。</strong></p> +<blockquote> +<p>注:Path 也可以使用<strong>Groups</strong>或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。</p> +</blockquote> +<p>Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。</p> +<p>Matter Path 使用规范:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;path&gt; = &lt;node&gt; &lt;endpoint&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span><span class="line"><span class="cl">&lt;path&gt; = &lt;group ID&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。</p> +<h4 id="14-定时和非定时timed--untimed">1.4 定时和非定时(Timed &amp; Untimed) +</h4><p>有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。</p> +<h3 id="2-read-transactions">2. Read Transactions +</h3><p>与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。</p> +<h4 id="21-读取请求操作read-request-action">2.1 读取请求操作(Read Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>在此 Action 中,Initiator 会查询 Target 提供的以下请求:</p> +<ul> +<li><strong>属性请求</strong>:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。</li> +<li><strong>事件请求</strong>:目标请求事件的零个或多个路径列表。</li> +</ul> +<p>目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141108121.png" +loading="lazy" +></p> +<h4 id="22-报告请求数据report-data-action">2.2 报告请求数据(Report Data Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>在此 Action 中,Target 响应:</p> +<ul> +<li><strong>属性报告(Attribute Reports)</strong>:读取操作请求中请求的零个或多个报告属性的列表。</li> +<li><strong>事件报告(Event Reports)</strong>:零个或多个报告事件的列表。</li> +<li><strong>抑制响应(Suppress Response)</strong>:一个标志,用于确定是否应抑制对此操作的<strong>状态响应。</strong></li> +<li><strong>订阅 ID(Subscription ID)</strong>:如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。</li> +</ul> +<h4 id="23-状态响应动作status-response-action">2.3 状态响应动作(Status Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者 -&gt; 目标</strong></p> +</blockquote> +<p>一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。</p> +<p>一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。</p> +<p>状态响应操作仅包含一个<strong>状态字段</strong>,该字段将确认操作成功或显示失败代码。</p> +<h3 id="3-subscription-transaction">3. Subscription Transaction +</h3><h4 id="31-订阅请求操作subscribe-request-action">3.1 订阅请求操作(Subscribe Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。</p> +<p>订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。</p> +<p>订阅请求操作包含:</p> +<ul> +<li><strong>Min Interval Floor(最小间隔层)</strong>:报告之间的最小间隔。</li> +<li><strong>Max Interval Ceiling(最大区间上限)</strong>:报告之间的最大间隔。</li> +<li>Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。</li> +<li>Event Reports(事件报告):零个或多个报告事件的列表。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141332135.png" +loading="lazy" +></p> +<p>在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:<strong>Primed Published Data</strong>。</p> +<p>然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。</p> +<p>目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。</p> +<h4 id="32-订阅响应操作subscribe-response-action">3.2 订阅响应操作(Subscribe Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>这是订阅交易的最后一个操作,并结束了该过程。这包括:</p> +<ul> +<li><strong>Subscription ID(订阅 ID)</strong>:标识订阅的整数。</li> +<li><strong>Min Interval(最小间隔)</strong>:最终确定的报告之间的最小间隔。</li> +<li><strong>Max Interval(最大间隔)</strong>:<em>最终</em>确定<em>的</em>报告之间的最大间隔。</li> +</ul> +<h3 id="4-write-transactions">4. Write Transactions +</h3><h4 id="41-不定时写入事务untimed-write-transaction">4.1 不定时写入事务(Untimed Write Transaction) +</h4><h5 id="411-写请求操作write-request-action">4.1.1 写请求操作(Write Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>与读取请求操作类似,在此操作中,发起者为目标提供:</p> +<ul> +<li><strong>Write Requests(写入请求)</strong>:包含路径和数据的一个或多个元组的列表。</li> +<li><strong>Timed Request(定时请求)</strong>:一个标志,指示此操作是否是定时写入事务的一部分。</li> +<li><strong>Suppress Response(抑制响应)</strong>:指示是否应抑制响应状态操作的标志。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141423081.png" +loading="lazy" +></p> +<h5 id="412-写响应操作write-response-action">4.1.2 写响应操作(Write Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<h5 id="413-不定时写入限制untimed-write-restrictions">4.1.3 不定时写入限制(Untimed Write Restrictions) +</h5><p>写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。</p> +<h4 id="42-定时写入事务timed-write-transaction">4.2 定时写入事务(Timed Write Transaction) +</h4><p>在定时写入事务中比非定时写入事务多了几个步骤。</p> +<h5 id="421-定时请求操作timed-request-action">4.2.1 定时请求操作(Timed request action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。</p> +<h5 id="422-写请求操作write-request-action">4.2.2 写请求操作(Write Request Action) +</h5><p>与前面描述的 <strong>4.1.1 写请求操作</strong> 相同。</p> +<h5 id="423-写响应操作write-response-action">4.2.3 写响应操作(Write Response Action) +</h5><p>与前面描述的 <strong>4.1.2 写响应操作</strong> 相同。</p> +<h5 id="424-定时写入限制timed-write-restrictions">4.2.4 定时写入限制(Timed Write Restrictions) +</h5><p>定时请求动作、写请求动作和写响应动作是单播的。</p> +<h3 id="5调用事务">5.调用事务 +</h3><p><strong>调用事务</strong>用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。</p> +<p>与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 <strong>交互模型:1.4.定时和非定时</strong></p> +<h4 id="51-不定时调用事务">5.1 不定时调用事务 +</h4><h5 id="511-调用请求操作invoke-request-action">5.1.1 调用请求操作(Invoke Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:</p> +<ul> +<li><strong>Invoke Requests(调用请求):集群命令</strong>的路径(PATH)列表 ,以及命令的可选参数,名为 <strong>Command Fields</strong>。</li> +<li>Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。</li> +<li>Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。</li> +<li><strong>Interaction ID</strong>:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。</li> +</ul> +<h5 id="512-调用响应操作invoke-response-action">5.1.2 调用响应操作(Invoke Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:</p> +<ul> +<li><strong>Invoke Responses(调用响应)</strong>:发送的每个调用请求的命令响应或状态列表。</li> +<li>Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。</li> +</ul> +<h5 id="513-不定时调用限制">5.1.3 不定时调用限制 +</h5><p>Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。</p> +<h4 id="52-定时调用事务">5.2 定时调用事务 +</h4><p>与定时写入事务类似,定时调用事务也从定时请求操作开始。</p> +<h5 id="521-定时请求操作">5.2.1 定时请求操作 +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141539988.png" +loading="lazy" +></p> +<h5 id="522-调用请求操作invoke-request-action">5.2.2 调用请求操作(Invoke Request Action) +</h5><p>与前面描述的 <strong>5.1.1 调用请求操作</strong> 相同。</p> +<h5 id="523-调用响应操作invoke-response-action">5.2.3 调用响应操作(Invoke Response Action) +</h5><p>与前面描述的 <strong>5.1.2 调用响应操作</strong> 相同。</p> +<h5 id="524-定时调用限制timed-invoke-restrictions">5.2.4 定时调用限制(Timed Invoke Restrictions) +</h5><p>所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。</p> +<p>Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。</p> +<hr> +<h2 id="参考资料">参考资料 +</h2><ul> +<li><a class="link" href="https://developers.home.google.com/matter/primer/device-data-model#parts_list" target="_blank" rel="noopener" +>https://developers.home.google.com/matter/primer/device-data-model#parts_list</a></li> +<li><a class="link" href="https://www.bilibili.com/video/BV1NL411T7Kj/?spm_id_from=333.788&amp;vd_source=40334d7415493efea293dacb3c13f0b4" target="_blank" rel="noopener" +>Matter技术及关键特性介绍</a></li> +</ul>【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul>【Matter】Matter环境构建参考文档https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/Wed, 24 May 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/<img src="https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/cover.jpg" alt="Featured image of post 【Matter】Matter环境构建参考文档" /><h1 id="matter-环境构建参考文档">Matter 环境构建参考文档 +</h1><hr> +<p>Matter支持用<a class="link" href="https://gn.googlesource.com/gn/" target="_blank" rel="noopener" +>GN</a>配置构建,一个快速且可扩展的元构建系统,生成输入到<a class="link" href="https://ninja-build.org/" target="_blank" rel="noopener" +>ninja</a>。</p> +<h2 id="经过测试的操作系统">经过测试的操作系统 +</h2><p>该构建系统已经在以下操作系统上进行了测试:</p> +<ul> +<li>macOS 10.15</li> +<li>Debian 11 (64 bit required)</li> +<li>Ubuntu 22.04 LTS</li> +</ul> +<h2 id="构建系统的特点">构建系统的特点 +</h2><p>Matter构建系统有以下特点:</p> +<ul> +<li>速度非常快,占用空间小</li> +<li>跨平台处理: Linux, Darwin, Embedded Arm, 等等</li> +<li>多种工具链和跨工具链的依赖性</li> +<li>集成了自动测试框架: ninja check</li> +<li>自省:&ldquo;gn desc&rdquo;。</li> +<li>自动格式化: <code>gn格式</code>。</li> +</ul> +<h2 id="检查matter的代码">检查Matter的代码 +</h2><p>要检查Matter资源库,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="同步子模块">同步子模块 +</h2><p>如果你已经签出了Matter的代码,运行下面的命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="先决条件">先决条件 +</h2><p>在构建之前,你必须安装一些操作系统的特定依赖。</p> +<h3 id="1在linux上安装先决条件">1.在Linux上安装先决条件 +</h3><p>在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\ +</span></span><span class="line"><span class="cl"> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev +</span></span><span class="line"><span class="cl"> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="用户界面的构建">用户界面的构建 +</h4><p>如果通过<code>build_examples.py</code>和<code>with-ui</code>变体构建,也要安装SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在macos上安装先决条件">2.在macOS上安装先决条件 +</h3><p>在macOS上,从 Mac App Store上安装 Xcode 。</p> +<h4 id="用户界面的构建-1">用户界面的构建 +</h4><p>如果构建<code>-with-ui</code>变体,也要安装 SDL2 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">brew install sdl2 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3在raspberry-pi-4上安装先决条件">3.在Raspberry Pi 4上安装先决条件 +</h3><p>完成以下步骤:</p> +<ol> +<li>使用:在 micro SD 卡上<code>rpi-imager</code>安装适用于 arm64 架构的 Ubuntu <em>22.04</em> 64 位<em>服务器操作系统。</em></li> +<li>启动SD卡。</li> +<li>用默认的用户账户 &ldquo;ubuntu &ldquo;和密码 &ldquo;ubuntu &ldquo;登录。</li> +<li>继续执行 <a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>在 Linux 上安装先决条件</a>。</li> +<li>安装一些Raspberry Pi的特定依赖项:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install pi-Bluetooth avahi-utils +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="6"> +<li>安装完 &ldquo;pi-bluetooth &ldquo;后,重新启动你的Raspberry Pi。</li> +</ol> +<h4 id="配置wpa_supplicant以存储永久变化">配置wpa_supplicant以存储永久变化 +</h4><p>默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:</p> +<ol> +<li>编辑 <code>dbus-fi.w1.wpa_supplicant1.service</code> 文件以使用配置文件来代替,运行以下命令:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="2"> +<li>运行以下命令,将wpa_supplicant的启动参数改为提供的值:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="3"> +<li>通过运行以下命令添加<code>wpa-supplicant</code>配置文件:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="4"> +<li>在<code>wpa-supplicant</code>文件中添加以下内容:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl_interface=DIR=/run/wpa_supplicant +</span></span><span class="line"><span class="cl">update_config=1 +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="5"> +<li>重新启动你的Raspberry Pi。</li> +</ol> +<h2 id="安装zap工具">安装ZAP工具 +</h2><p><code>bootstrap.sh</code>将下载一个兼容的ZAP工具版本并将其设置在<code>$PATH</code>。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a> 页面下载。</p> +<h3 id="1linux-arm">1.Linux ARM +</h3><p>Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置<code>$ZAP_DEVELOPMENT_PATH</code>(见下面 <code>使用哪种ZAP</code>一节)。</p> +<p>文件<code>scripts/setup/zap.json</code>包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a>。要作为源代码签出代码,相应的标签应该存在于zap中<a class="link" href="https://github.com/project-chip/zap/tags" target="_blank" rel="noopener" +>repository tags</a> 列表中。</p> +<p>命令示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">RUN <span class="nb">set</span> -x <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> mkdir -p /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git clone https://github.com/project-chip/zap.git /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git checkout <span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm config <span class="nb">set</span> user <span class="m">0</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm ci +</span></span><span class="line"><span class="cl">ENV <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2使用哪种zap">2.使用哪种ZAP +</h3><p>ZAP工具脚本使用以下检测,按重要性排序:</p> +<ul> +<li> +<p><code>$ZAP_DEVELOPMENT_PATH</code>指向一个ZAP检出。</p> +</li> +<li> +<p>如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。</p> +</li> +<li> +<p><code>$ZAP_INSTALL_PATH</code>指向<code>zap-linux.zip</code>或`zap-m</p> +</li> +</ul> +<h2 id="为构建做准备">为构建做准备 +</h2><p>在运行任何其他构建命令之前,<code>scripts/activate.sh</code>的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。</p> +<p>运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1更新环境">1.更新环境 +</h3><p>如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>脚本 <code>scripts/bootstrap.sh</code>从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。</p> +<h2 id="为主机操作系统linux或macos进行构建">为主机操作系统(Linux或macOS)进行构建 +</h2><p>运行以下命令,为主机平台构建所有的源代码、库和测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些命令生成了一个适合调试的配置。要配置一个构建,请指定<code>is_debug=false</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/host --args=&#39;is_debug=false&#39; 。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**目录名称 &ldquo;out/host &ldquo;可以是任何目录,通常是在<code>out</code>目录下构建。这个例子使用 <code>host</code> 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过<code>gn args</code>重新配置。</p> +</blockquote> +<p>要运行所有测试,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host check +</span></span></code></pre></td></tr></table> +</div> +</div><p>要想只运行<code>src/inet/tests</code>中的测试,可以运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host src/inet/tests:test_run +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja: no work to do +</span></span></code></pre></td></tr></table> +</div> +</div><p>这意味着测试在之前的构建中通过了。</p> +</blockquote> +<h2 id="使用build_examplespy">使用<code>build_examples.py</code> +</h2><p>该脚本<code>./scripts/build/build_examples.py</code>提供了一个统一的编译构建接口,可以使用<code>gn</code>、<code>cmake</code>、<code>ninja</code>和其他必要的工具来编译各种平台。</p> +<p>使用 <code>./scripts/build/build_examples.py targets</code> 来查看支持的目标。</p> +<p>构建命令的例子:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 编译并在主机上运行所有测试: +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang) +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个esp32的例子 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个 nrf 示例 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1libfuzzer单元测试">1.<code>libfuzzer</code>单元测试 +</h3><p><code>libfuzzer</code>单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如<code>asan</code>应该被使用。</p> +<p>可执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build +</span></span></code></pre></td></tr></table> +</div> +</div><p>之后,测试应该被定位在<code>out/linux-x64-tests-lang-asan-libfuzzer/tests/</code>。</p> +<h4 id="ossfuzz的配置"><code>ossfuzz</code>的配置 +</h4><p><code>ossfuzz</code>配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如<code>$CFLAGS</code>、<code>$CXXFLAGS</code>和<code>$lib_fuzzing_engine</code>。</p> +<p>你可能需要<code>libfuzzer</code>+<code>asan</code>的构建来代替本地测试。</p> +<h2 id="构建自定义配置">构建自定义配置 +</h2><p>构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:</p> +<ul> +<li>将<code>--args</code>选项传递给<code>gn gen</code>。</li> +<li>在输出目录上运行<code>gn args</code>。</li> +<li>编辑输出目录下的<code>args.gn</code>。</li> +</ul> +<p>要配置一个新的构建或编辑现有构建的参数,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn args out/custom +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><p>两个关键的内置构建参数是 <code>target_os</code> 和 <code>target_cpu</code>,它们分别控制构建的操作系统和CPU。</p> +<p>要查看所有可用的构建参数的帮助,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/custom +</span></span><span class="line"><span class="cl">gn args --list out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="构建实例">构建实例 +</h2><p>你可以通过两种方式构建例子。</p> +<h3 id="1将例子作为独立的项目来构建">1.将例子作为独立的项目来构建 +</h3><p>要把例子作为单独的项目来构建,在Matter的<code>third_party directory</code>,运行下面的命令,输入正确的路径到例子的正确路径(这里是 &ldquo;chip-shell&rdquo;):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd examples/shell +</span></span><span class="line"><span class="cl">gn gen out/debug +</span></span><span class="line"><span class="cl">ninja -C out/debug +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在顶层建立实例">2.在顶层建立实例 +</h3><p>你可以在Matter项目的顶层构建例子。请看下面的<code>统一构建</code>一节了解详情。</p> +<h2 id="统一构建">统一构建 +</h2><p>要构建一个近似于连续构建集的统一配置,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34;&#39; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/unified all +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。</p> +<p>这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/unified host_gcc +</span></span><span class="line"><span class="cl">ninja -C out/unified check_host_gcc +</span></span></code></pre></td></tr></table> +</div> +</div><p>用配置的名称替换<code>host_gcc</code>,它可以在根目录下的 &ldquo;BUILD.gn &ldquo;中找到。</p> +<p>你也可以用参数对生成的配置进行微调。比如说</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34; enable_host_clang_build=false&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><p>完整的列表请参见根目录<code>BUILD.gn</code>。</p> +<p>在统一的构建中,目标有多个实例,需要通过添加通过添加<code>(toolchain)</code>后缀来区分。使用<code>gn ls out/debug</code>来列出所有的目标实例。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">desc</span> <span class="n">out</span><span class="o">/</span><span class="n">unified</span> <span class="s1">&#39;//src/controller(//build/toolchain/host:linux_x64_clang)&#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 +必须作为构建参数提供。例如,要添加 <code>Simplelink cc13x2_26x2</code> 例子到统一构建中,安装<a class="link" href="https://www.ti.com/tool/SYSCONFIG" target="_blank" rel="noopener" +>SysConfig</a> 并添加以下构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#34;target_os=\&#34;all\&#34; enable_ti_simplelink_builds=true &gt; ti_sysconfig_root=\&#34;/path/to/sysconfig\&#34;&#34; +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<h2 id="获得帮助">获得帮助 +</h2><p>GN集成了帮助,你可以通过<code>gn help</code>命令访问。</p> +<p>请确保查看以下推荐的主题:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn帮助执行</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="err">语法</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="n">toolchain</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可参见 <a class="link" href="https://gn.googlesource.com/gn/&#43;/master/docs/quick_start.md" target="_blank" rel="noopener" +>快速入门指南</a>。</p> +<h2 id="自省">自省 +</h2><p>GN有各种自省工具来帮助你检查构建配置。下面的例子以<code>out/host</code>输出目录为例:</p> +<ul> +<li> +<p>显示一个输出目录中的所有目标:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn ls out/host +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示所有将被构建的文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn output out/host &#39;*&#39; +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示配置的目标的GN表示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/inet --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>将整个构建的GN表示转为JSON格式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host/ &#39;*&#39; --all --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示依赖关系树:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //:all deps --tree --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>查找依赖性路径:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn path out/host //src/transport/tests:test //src/system +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>列出与`libCHIP&rsquo;连接的有用信息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/lib include_dirs +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib defines +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib outputs +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 一切都是JSON格式 +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h2 id="覆盖范围">覆盖范围 +</h2><p>代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。</p> +<p>运行以下命令来启动该脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build_coverage.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> -c, --code 指定收集覆盖数据的范围。 +</span></span><span class="line"><span class="cl"> core&#34;:从Matter SDK的核心堆栈中收集覆盖数据。--default +</span></span><span class="line"><span class="cl"> clusters&#34;:从Matter SDK中的cluster实现中收集覆盖数据。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;:收集Matter SDK的覆盖数据。 +</span></span><span class="line"><span class="cl"> -t, --tests 指定哪些工具来运行覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;unit&#39;: 运行单元测试来驱动覆盖率检查。--default +</span></span><span class="line"><span class="cl"> &#39;yaml&#39;: 运行yaml测试来驱动覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;: 运行单元和yaml测试来驱动覆盖率检查。 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): <a class="link" href="https://matter-build-automation.ue.r.appspot.com/" target="_blank" rel="noopener" +>matter coverage</a>。</p> +<h2 id="维护事项">维护事项 +</h2><p>如果你对GN构建系统做了任何改变,下一次构建会自动重新生成<code>ninja</code>文件。不需要做任何事情。</p>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/Sat, 06 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/<img src="https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover.jpg" alt="Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)" /><h1 id="esp-matter环境下的应用实践">esp-matter环境下的应用实践 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><p>请确保你本地已经配置好 <code>esp-idf</code> 及<code>esp-matter</code>环境,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130484975?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter开发环境搭建</a></p> +<h2 id="设置环境变量">设置环境变量 +</h2><h3 id="1esp-idf">1.ESP-IDF +</h3><p>根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041609281.png" +loading="lazy" +alt="image-20230504160909004" +></p> +<h3 id="2esp-matter">2.ESP-Matter +</h3><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>Linux</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>macOS</a></li> +</ul> +<p>由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>此处</a></p> +<p>在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>准备编译matter所需环境。注:如切换了其他分支需要重新运行</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060133538.png" +loading="lazy" +alt="image-20230506013329415" +></p> +<p>激活编译matter环境</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041611578.png" +loading="lazy" +alt="image-20230504161123505" +></p> +<h2 id="matter-example编译下载">Matter Example编译下载 +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2选择esp设备">2.选择esp设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>初次执行这个命令发生了如下报错:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">AttributeError</span><span class="p">:</span> <span class="err">&#39;</span><span class="n">HTTPResponse</span><span class="err">&#39;</span> <span class="n">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="err">&#39;</span><span class="n">strict</span><span class="err">&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在GitHub上参考此<a class="link" href="https://github.com/espressif/esp-idf/issues/11340" target="_blank" rel="noopener" +>issue</a>,并执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时重新执行esp-matter安装脚本:</p> +<p>由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此<a class="link" href="https://github.com/kurisaW/Summer-of-Open-Source/issues/7" target="_blank" rel="noopener" +>issue</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="p">.</span><span class="n">environment</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后回到示例工程下继续执行esp设备选择</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时发生了新的错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060221146.png" +loading="lazy" +alt="image-20230506022134054" +></p> +<p>由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">rm</span> <span class="o">-</span><span class="n">r</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span><span class="o">/</span><span class="n">build</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后成功解决问题:</p> +<p><img src="https://user-images.githubusercontent.com/98592772/236539480-35af78e1-382f-4092-a25b-fb2a09004d0a.png" +loading="lazy" +alt="b372338ad9384db034000d7839549b5" +></p> +<h3 id="3编译工程">3.编译工程 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060250998.png" +loading="lazy" +alt="image-20230506025001282" +></p> +<h3 id="4sdk烧写">4.SDK烧写 +</h3><p>第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">erase_flash</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060252819.png" +loading="lazy" +alt="image-20230506025047817" +></p> +<p>烧录程序并打开串口监视</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>可以看到烧录进度:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060251334.png" +loading="lazy" +alt="image-20230506025133178" +></p> +<p>包括串口监视器的提示信息,同时执行以下命令可退出串口监视:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">CTRL</span> <span class="o">+</span> <span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060254172.png" +loading="lazy" +alt="image-20230506025401001" +></p> +<p>那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。</p> +<hr> +<p>参考链接:</p> +<p><a class="link" href="https://blog.csdn.net/hydfxy2018/article/details/122041168?spm=1001.2101.3001.6650.11&amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;utm_relevant_index=12" target="_blank" rel="noopener" +>Matter Over Wifi 例程体验(CHIP Over Wifi)</a></p> +<p><a class="link" href="https://blog.csdn.net/weixin_40209493/article/details/125814311?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168324979316800211536064%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=168324979316800211536064&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-125814311-null-null.142%5ev86%5econtrol_2,239%5ev2%5einsert_chatgpt&amp;utm_term=matter%E6%8A%A5%E9%94%99&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>ESP-Matter 环境测试</a></p> +<p><a class="link" href="https://blog.csdn.net/puweiqi/article/details/129474079?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;utm_relevant_index=3" target="_blank" rel="noopener" +>matter搭建环境</a></p> +<p><a class="link" href="https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html" target="_blank" rel="noopener" +>https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html</a></p>【Matter】esp-matter开发环境搭建https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【Matter】esp-matter开发环境搭建" /><h1 id="esp-matter开发环境搭建">esp-matter开发环境搭建 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><h3 id="1ubuntu2204磁盘容量不小于80g">1.Ubuntu22.04(磁盘容量不小于80G) +</h3><h3 id="2科学上网环境">2.科学上网环境 +</h3><p>由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。</p> +<p>参考链接:<a class="link" href="https://kurisaw.github.io/p/%e7%bb%8f%e9%aa%8c%e5%88%86%e4%ba%ablinux-%e7%8e%af%e5%a2%83%e4%b8%8bv2ray%e7%9a%84%e4%bd%bf%e7%94%a8/" target="_blank" rel="noopener" +>【经验分享】Linux 环境下v2ray的使用</a></p> +<h2 id="esp-idf-开发环境搭建">esp-idf 开发环境搭建 +</h2><h3 id="1esp-idf-依赖环境安装">1.ESP-IDF 依赖环境安装 +</h3><blockquote> +<p>参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:</p> +<ul> +<li>Problem1:执行 git submodule 速度慢</li> +<li>Problem2:执行install.sh 速度慢</li> +</ul> +<p>所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。</p> +<h3 id="2problem1-solution">2.Problem1 solution +</h3><p>首先使用递归克隆命令克隆整个仓库到文件夹下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-idf.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span> <span class="o">--</span><span class="n">recursive</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:</p> +<ul> +<li>jihu-mirror 使用(推荐)</li> +<li>submodule-update 使用(不推荐)</li> +</ul> +<h4 id="21--jihu-mirror-使用推荐">2.1 jihu-mirror 使用(推荐) +</h4><ul> +<li>Step 1:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-gitee-tools.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Step 2:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 使用如下命令将仓库的 URL 进行替换: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">url</span><span class="p">.</span><span class="nl">https</span><span class="p">:</span><span class="c1">//jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>当我们使用命令 <code>git clone https://github.com/espressif/esp-idf</code> 时,默认的 URL <code>https://github.com/espressif/esp-idf</code> 将被自动替换成 <code>https://jihulab.com/esp-mirror/espressif/esp-idf</code>。</p> +<ul> +<li>Step 3:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 启用镜像URL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">set</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用命令 <code>./jihu-mirror.sh unset</code> 恢复,不使用镜像的 URL。</p> +<ul> +<li>Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recursive https://github.com/espressif/esp-idf.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然如果不想使用镜像的URL可以使用如下命令进行恢复:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">unset</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22--submodule-update-使用不推荐">2.2 submodule-update 使用(不推荐) +</h4><ul> +<li> +<p>Step 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">gitee</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">EspressifSystems</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">.</span><span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>Step 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 仅克隆 esp-idf,不包含子模块 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-idf.git +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<ul> +<li>Step 3:</li> +</ul> +<p>可以有两种方式来更新 submodules。</p> +<ul> +<li> +<p>方式一</p> +<p>进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">EGT_PATH</span><span class="o">=$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入 esp-idf 目录执行 submodule-update.sh 脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd esp-idf +</span></span><span class="line"><span class="cl">$EGT_PATH/submodule-update.sh +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>方式二</p> +<p><code>submodule-update.sh</code> 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:<code>submodule-update.sh PATH_OF_PROJ</code>。</p> +<p>假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="o">./</span><span class="n">submodule</span><span class="o">-</span><span class="n">update</span><span class="o">.</span><span class="n">sh</span> <span class="o">~/</span><span class="n">git</span><span class="o">/</span><span class="n">esp32</span><span class="o">-</span><span class="n">sdk</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果要更新其他工程,可以同样方式。</p> +</li> +</ul> +<blockquote> +<p>值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!</p> +</blockquote> +<h3 id="3problem2-solution">3.Problem2 solution +</h3><p>下面说第二个问题:执行./install.sh速度慢的问题</p> +<p>在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 <code>IDF_GITHUB_ASSETS</code> 的环境变量来指定这个地址。在设置了 <code>IDF_GITHUB_ASSETS</code> 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">export</span> <span class="n">IDF_GITHUB_ASSETS</span><span class="o">=</span><span class="s">&#34;dl.espressif.com/github_assets&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后再执行安装命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这还报了一个错误</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041247286.png" +loading="lazy" +alt="image-20230504124717772" +></p> +<p>我们根据提示安装<code>python3.10-venv</code>,并再次执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="mf">.10</span><span class="o">-</span><span class="n">venv</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041249721.png" +loading="lazy" +alt="image-20230504124913620" +></p> +<p>至此,esp-idf 的安装工具就告一段落了。</p> +<h2 id="esp-matter开发环境搭建-1">esp-matter开发环境搭建 +</h2><blockquote> +<p>参考:<a class="link" href="https://github.com/espressif/esp-matter" target="_blank" rel="noopener" +>【乐鑫 Matter SDK GitHub】</a></p> +</blockquote> +<p>**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:<code>./jihu-mirror.sh unset</code>取消esp镜像!! **</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-matter.git +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git submodule update --init --recursive +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错&hellip;</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): started +</span></span><span class="line"><span class="cl"> error: subprocess-exited-with-error +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> × python setup.py bdist_wheel did not run successfully. +</span></span><span class="line"><span class="cl"> │ exit code: 1 +</span></span><span class="line"><span class="cl"> ╰─&gt; See above for output. +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> note: This error originates from a subprocess, and is likely not a problem with pip. +</span></span><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): finished with status &#39;error&#39; +</span></span><span class="line"><span class="cl"> ERROR: Failed building wheel for pycryptodome +</span></span><span class="line"><span class="cl"> Running setup.py clean for pycryptodome +</span></span><span class="line"><span class="cl"> Building wheel for gevent (pyproject.toml): started +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ...... +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们查看<code>install.sh</code>文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">basedir</span><span class="o">=</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">ESP_MATTER_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="nb">pwd</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">MATTER_PATH</span><span class="o">=</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">export</span> ESP_MATTER_PATH +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Running Matter Setup&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/scripts/bootstrap.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Run the zap_download.py and extract the path of installed binary</span> +</span></span><span class="line"><span class="cl"><span class="c1"># eg output before cut: &#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># output after cut: zap/zap-v2023.03.06-nightly</span> +</span></span><span class="line"><span class="cl"><span class="c1"># TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged</span> +</span></span><span class="line"><span class="cl"><span class="nv">zap_path</span><span class="o">=</span><span class="sb">`</span>python3 <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --sdk-root <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --extract-root .zap 2&gt;/dev/null <span class="p">|</span> cut -d<span class="o">=</span> -f2<span class="sb">`</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Check whether the download is successful.</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="nv">$zap_path</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Failed to install zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"> deactivate +</span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span><span class="s2">/.zap&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> rm -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl">mkdir <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl">mv <span class="nv">$zap_path</span>/* <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/ +</span></span><span class="line"><span class="cl">rm -r <span class="nv">$zap_path</span> +</span></span><span class="line"><span class="cl">chmod +x <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/zap-cli +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Building host tools&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">gn --root<span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">&#34;</span> gen <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl">ninja -C <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Host tools built at: </span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">/out/host&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Exit Matter environment&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">deactivate +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for mfg_tool&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/tools/mfg_tool/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for Matter&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;All done! You can now run:&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34; . </span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">/export.sh&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install build-essential python3-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pkg-config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" +loading="lazy" +alt="image-20230504145216015" +></a></p> +<p>接着在安装<code>zap-cli</code>的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./install.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" +loading="lazy" +alt="image-20230504150238105" +></a></p> +<p>最后看到<code>All done!</code>即代表环境安装成功!</p> +<p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" +loading="lazy" +alt="image-20230504153243388" +></a></p> +<p>至此,esp-matter开发环境搭建成功!</p>【经验分享】Linux环境下v2ray的使用https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/cover.jpg" alt="Featured image of post 【经验分享】Linux环境下v2ray的使用" /><h1 id="linux-环境下v2ray的使用">Linux 环境下v2ray的使用 +</h1><hr> +<blockquote> +<p>v2ray官方文档:<a class="link" href="https://v2raya.org/" target="_blank" rel="noopener" +>https://v2raya.org/</a></p> +</blockquote> +<h2 id="curl安装">curl安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">apt-get purge libcurl4 +</span></span><span class="line"><span class="cl">apt-get install curl +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray镜像脚本安装">v2ray镜像脚本安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">curl</span> <span class="o">-</span><span class="n">Ls</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.v2raya.org/go.sh | sudo bash +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041040498.png" +loading="lazy" +alt="image-20230504104013149" +></p> +<p>出现该提示信息则表示安装成功:<code>info: V2Ray v5.4.1 is installed.</code></p> +<p>接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">disable</span> <span class="n">v2ray</span> <span class="o">--</span><span class="n">now</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray软件安装">v2ray软件安装 +</h2><blockquote> +<p>仓库release地址:<a class="link" href="https://github.com/v2rayA/v2rayA/releases" target="_blank" rel="noopener" +>https://github.com/v2rayA/v2rayA/releases</a></p> +</blockquote> +<p>选择合适自己 Linux 内核架构,可以使用<code>dpkg --print-architecture</code>查看</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041050162.png" +loading="lazy" +alt="image-20230504105029122" +></p> +<p>这里我选择``下载到 Linux 共享文件夹</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041052416.png" +loading="lazy" +alt="image-20230504105226313" +></p> +<p>将共享文件夹下的<code>installer_debian_amd64_2.0.5.deb</code>文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041054352.png" +loading="lazy" +alt="image-20230504105440300" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041053522.png" +loading="lazy" +alt="image-20230504105340371" +></p> +<h2 id="启动v2raya进程">启动v2raya进程 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">start</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="设置开机自启动">设置开机自启动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">enable</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray使用">v2ray使用 +</h2><p>打开火狐浏览器,输入 http://localhost:2017/</p> +<p>输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041058629.png" +loading="lazy" +alt="image-20230504105825544" +></p> +<p>导入我们的机场订阅地址</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041100916.png" +loading="lazy" +alt="image-20230504105925321" +></p> +<p>选择想要使用的节点后,点击 Ready</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041106172.png" +loading="lazy" +alt="image-20230504110635073" +></p> +<h2 id="v2ray-settings">v2ray Settings +</h2><p>我们点击网页上右上角的Setting,进行如下修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041110129.png" +loading="lazy" +alt="image-20230504111011073" +></p> +<h2 id="测试">测试 +</h2><p>至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041111183.png" +loading="lazy" +alt="image-20230504111116983" +></p>【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div>Github同步Gitee镜像仓库自动化脚本https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/Tue, 11 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover.jpg" alt="Featured image of post Github同步Gitee镜像仓库自动化脚本" /><h1 id="github同步gitee镜像仓库自动化脚本">Github同步Gitee镜像仓库自动化脚本 +</h1><hr> +<h2 id="前言">前言 +</h2><p>在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。</p> +<h2 id="什么是hub-mirror-action">什么是Hub Mirror Action? +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111537579.png" +loading="lazy" +alt="image-20230411153729450" +></p> +<h3 id="1介绍">1.介绍 +</h3><p><a class="link" href="https://github.com/marketplace/actions/hub-mirror-action" target="_blank" rel="noopener" +>Hub Mirror Action</a>是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。</p> +<h3 id="2用法">2.用法 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Mirror the Github organization repos to Gitee.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># src_account_type: org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># dst_account_type: org</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:详细使用案例请查看官方仓库 <a class="link" href="https://github.com/Yikun/hub-mirror-action" target="_blank" rel="noopener" +>https://github.com/Yikun/hub-mirror-action</a></p> +<h2 id="配置步骤">配置步骤 +</h2><h3 id="1生成密钥对">1.生成密钥对 +</h3><p>我们先在本地使用git命令行打开终端,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ssh</span><span class="o">-</span><span class="n">keygen</span> <span class="o">-</span><span class="n">t</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">f</span> <span class="o">~/</span><span class="n">Documents</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">key</span><span class="o">/</span><span class="n">id_rsa</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注:请确保文件夹<code>~/Documents/ssh-key/</code>存在,当然你也可以选择放置在其他地方</p> +<p>过程中一路回车即可,注意不要设置密码。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111543237.png" +loading="lazy" +alt="image-20230411154330166" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111551053.png" +loading="lazy" +alt="image-20230411155124878" +></p> +<h3 id="2github私钥配置">2.GitHub私钥配置 +</h3><p>首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111547966.png" +loading="lazy" +alt="image-20230411154716849" +></p> +<ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_PRIVATE_KEY</code>的secret,值为我们之前生成的密钥对中的私钥(id_rsa)</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111553202.png" +loading="lazy" +alt="image-20230411155314101" +></p> +<h3 id="3gitee公钥配置">3.Gitee公钥配置 +</h3><p>我们打开Gitee账号,进入<code>Settings-&gt;安全设置-&gt;SSH公钥</code></p> +<p>添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111558684.png" +loading="lazy" +alt="image-20230411155846562" +></p> +<h3 id="4gitee生成私人令牌">4.Gitee生成私人令牌 +</h3><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111559999.png" +loading="lazy" +alt="image-20230411155958898" +></p> +<p>令牌名称随意,同时复制生成的令牌值。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111601466.png" +loading="lazy" +alt="image-20230411160127393" +></p> +<h3 id="5github绑定gitee令牌">5.Github绑定Gitee令牌 +</h3><ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_TOKEN</code>的secret,值为Gitee生成的令牌值</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111603849.png" +loading="lazy" +alt="image-20230411160340721" +></p> +<h3 id="6编写ci脚本">6.编写CI脚本 +</h3><p>将<code>ci_bot</code>仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="n">ci_bot</span><span class="o">/</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="p">.</span><span class="n">github</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">workflows</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">Sync</span><span class="p">.</span><span class="n">yml</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>Sync.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">push, delete, create ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出后,将本次修改push到远端仓库。</p> +<p>查看Action运行情况:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111611887.png" +loading="lazy" +alt="image-20230411161143741" +></p> +<h3 id="7多仓库同步推送">7.多仓库同步推送 +</h3><p>如果你想同时同步多个仓库,只需要完成如下修改</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">static_list 默认为&#39;&#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111633375.png" +loading="lazy" +alt="image-20230411163307283" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111631352.png" +loading="lazy" +alt="image-20230411163135259" +></p> +<h3 id="8定时运行脚本">8.定时运行脚本 +</h3><p>为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:</p> +<p>修改Sync.yml文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 0 * * *&#39;</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">delete</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">create</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111731377.png" +loading="lazy" +alt="image-20230411173142865" +></p> +<h2 id="总结">总结 +</h2><p>通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。</p>【网络编程】OSI七层模型&TCPIP四层模型https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/<img src="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover.jpg" alt="Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型" /><h2 id="osi七层模型">OSI七层模型 +</h2><p>七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。</p> +<h4 id="1物理层">1.物理层 +</h4><p><code>建立、维护、断开物理连接。</code>(由底层网络定义协议)</p> +<p>机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。</p> +<p>应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。</p> +<h4 id="2数据链路层">2.数据链路层 +</h4><p><code>建立逻辑连接、进行硬件地址寻址、差错校验等功能。</code>(由底层网络定义协议)</p> +<p>将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)</p> +<h4 id="3网络层">3.网络层 +</h4><p><code>进行逻辑地址寻址,实现不同网络之间的路径选择。</code></p> +<p>控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)</p> +<h4 id="4传输层">4.传输层 +</h4><p><code>定义传输数据的协议端口号,以及流控和差错校验。</code> +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层</p> +<h4 id="5会话层">5.会话层 +</h4><p><code>建立、管理、终止会话。</code>(在五层模型里面已经合并到了应用层)</p> +<p>不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)</p> +<h4 id="6表示层">6.表示层 +</h4><p><code>数据的表示、安全、压缩。</code>(在五层模型里面已经合并到了应用层)</p> +<p>信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)</p> +<h4 id="7应用层">7.应用层 +</h4><p><code>网络服务与最终用户的一个接口</code></p> +<p>各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)</p> +<hr> +<h2 id="tcpip-四层模型">TCP/IP 四层模型 +</h2><p>TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是<strong>指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇</strong>, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304101020851.png" +loading="lazy" +alt="20201028134158932" +></p> +<p>TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示</p> +<h4 id="1应用层">1.应用层 +</h4><p><code>应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。</code></p> +<ul> +<li>应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次</li> +<li>对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议</li> +<li>应用层还能加密、解密、格式化数据</li> +<li>应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源</li> +</ul> +<h4 id="2传输层">2.传输层 +</h4><p><code>作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用</code></p> +<h4 id="3网络层-1">3.网络层 +</h4><p><code>网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能</code></p> +<h4 id="4网络接口层">4.网络接口层 +</h4><p><code>在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路</code></p>Wireshark网络抓包教程https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover.jpg" alt="Featured image of post Wireshark网络抓包教程" /><blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/HarveyH/article/details/113731485" target="_blank" rel="noopener" +>转自:WireShark 抓包使用教程&ndash;详细</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:</p> +<p>1、Wireshark软件下载和安装以及Wireshark主界面介绍。</p> +<p>2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。</p> +<p>3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。</p> +<h2 id="wireshark软件安装">Wireshark软件安装 +</h2><p>软件下载路径:<a class="link" href="https://www.wireshark.org/" target="_blank" rel="noopener" +>wireshark官网</a>。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。</p> +<p>如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:<a class="link" href="http://www.win10pcap.org/download/" target="_blank" rel="noopener" +>win10pcap兼容性安装包</a></p> +<h2 id="wireshark-开始抓包示例"><strong>Wireshark 开始抓包示例</strong> +</h2><p>先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。</p> +<p>1、打开wireshark 2.6.5,主界面如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102042369.png" +loading="lazy" +alt="image-20230410204240214" +></p> +<p>2、选择菜单栏上Capture -&gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043634.png" +loading="lazy" +alt="image-20230410204301558" +></p> +<p>3、wireshark启动后,wireshark处于抓包状态中。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043120.png" +loading="lazy" +alt="image-20230410204330881" +></p> +<p>4、执行需要抓包的操作,如ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>。</p> +<p>5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043973.png" +loading="lazy" +alt="image-20230410204349768" +></p> +<p>5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。</p> +<h2 id="wireshakr抓包界面">Wireshakr抓包界面 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044121.png" +loading="lazy" +alt="image-20230410204417023" +></p> +<p>说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --&gt; Coloring Rules。如下所示</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044221.png" +loading="lazy" +alt="image-20230410204435065" +></p> +<p><strong>WireShark 主要分为这几个界面</strong></p> +<p>1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --&gt; Display Filters。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045496.png" +loading="lazy" +alt="image-20230410204500320" +></p> +<p>2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045343.png" +loading="lazy" +alt="image-20230410204525166" +></p> +<p>3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为</p> +<p>(1)Frame: 物理层的数据帧概况</p> +<p>(2)Ethernet II: 数据链路层以太网帧头部信息</p> +<p>(3)Internet Protocol Version 4: 互联网层IP包头部信息</p> +<p>(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP</p> +<p>(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045382.png" +loading="lazy" +alt="image-20230410204540297" +></p> +<p><strong>TCP包的具体内容</strong></p> +<p>从下图可以看到wireshark捕获到的TCP包中的每个字段。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045329.png" +loading="lazy" +alt="image-20230410204557194" +></p> +<p>4. Dissector Pane(数据包字节区)。</p> +<h2 id="wireshark过滤器设置">Wireshark过滤器设置 +</h2><p>初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。</p> +<p>(1)抓包过滤器</p> +<p>捕获过滤器的菜单栏路径为Capture --&gt; Capture Filters。用于<strong>在抓取数据包前设置。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046204.png" +loading="lazy" +alt="image-20230410204620124" +></p> +<p>如何使用?可以在抓取数据包前设置如下。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046995.png" +loading="lazy" +alt="image-20230410204653927" +></p> +<p>ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047470.png" +loading="lazy" +alt="image-20230410204717268" +></p> +<p>(2)显示过滤器</p> +<p>显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047185.png" +loading="lazy" +alt="image-20230410204734985" +></p> +<p>执行ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取的数据包列表如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047584.png" +loading="lazy" +alt="image-20230410204753507" +></p> +<p>观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048361.png" +loading="lazy" +alt="image-20230410204815301" +></p> +<p>上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。</p> +<p><strong>wireshark过滤器表达式的规则</strong></p> +<p>1、抓包过滤器语法和实例</p> +<p>抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&amp;&amp; 与、|| 或、!非)</p> +<p>(1)协议过滤</p> +<p>比较简单,直接在抓包过滤框中直接输入协议名即可。</p> +<p>TCP,只显示TCP协议的数据包列表</p> +<p>HTTP,只查看HTTP协议的数据包列表</p> +<p>ICMP,只显示ICMP协议的数据包列表</p> +<p>(2)IP过滤</p> +<p>host 192.168.1.104</p> +<p>src host 192.168.1.104</p> +<p>dst host 192.168.1.104</p> +<p>(3)端口过滤</p> +<p>port 80</p> +<p>src port 80</p> +<p>dst port 80</p> +<p>(4)逻辑运算符&amp;&amp; 与、|| 或、!非</p> +<p>src host 192.168.1.104 &amp;&amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包</p> +<p>host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包</p> +<p>!broadcast 不抓取广播数据包</p> +<p>2、显示过滤器语法和实例</p> +<p>(1)比较操作符</p> +<p>比较操作符有== 等于、!= 不等于、&gt; 大于、&lt; 小于、&gt;= 大于等于、&lt;=小于等于。</p> +<p>(2)协议过滤</p> +<p>比较简单,直接在Filter框中直接输入协议名即可。<strong>注意:协议名称需要输入小写。</strong></p> +<p>tcp,只显示TCP协议的数据包列表</p> +<p>http,只查看HTTP协议的数据包列表</p> +<p>icmp,只显示ICMP协议的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048252.png" +loading="lazy" +alt="image-20230410204852057" +></p> +<p>(3) ip过滤</p> +<p>ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表</p> +<p>ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表</p> +<p>ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049772.png" +loading="lazy" +alt="image-20230410204937591" +></p> +<p>(4)端口过滤</p> +<p>tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。</p> +<p>tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。</p> +<p>tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049752.png" +loading="lazy" +alt="image-20230410204953546" +></p> +<p>(5) Http模式过滤</p> +<p>http.request.method==&ldquo;GET&rdquo;, 只显示HTTP GET方法的。</p> +<p>(6)逻辑运算符为 and/or/not</p> +<p>过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050123.png" +loading="lazy" +alt="image-20230410205019907" +></p> +<p>(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050553.png" +loading="lazy" +alt="image-20230410205039366" +></p> +<p>右键单击选中后出现如下界面</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050685.png" +loading="lazy" +alt="image-20230410205054595" +></p> +<p>选中Select后在过滤器中显示如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051573.png" +loading="lazy" +alt="image-20230410205109402" +></p> +<p>后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含&quot;abcd&quot;内容的数据流。<strong>包含的关键词是contains 后面跟上内容。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051902.png" +loading="lazy" +alt="image-20230410205121718" +></p> +<p>看到这, 基本上对wireshak有了初步了解。</p> +<h2 id="wireshark抓包分析tcp三次握手">Wireshark抓包分析TCP三次握手 +</h2><p>(1)TCP三次握手连接建立过程</p> +<p>Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;</p> +<p>Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;</p> +<p>Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051845.png" +loading="lazy" +alt="image-20230410205135665" +></p> +<p>(2)wireshark抓包获取访问指定服务端数据包</p> +<p>Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。</p> +<p>Step2:使用ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取IP。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051433.png" +loading="lazy" +alt="image-20230410205150253" +></p> +<p>Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052925.png" +loading="lazy" +alt="image-20230410205200760" +></p> +<p>图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。</p> +<p><strong>第一次握手数据包</strong></p> +<p>客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052226.png" +loading="lazy" +alt="image-20230410205215079" +></p> +<p>数据包的关键属性如下:</p> +<p>SYN :标志位,表示请求建立连接</p> +<p>Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据</p> +<p>Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据</p> +<p><strong>第二次握手的数据包</strong></p> +<p>服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052307.png" +loading="lazy" +alt="image-20230410205230236" +></p> +<p>数据包的关键属性如下:</p> +<p>[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK</p> +<p>Seq = 0 :初始建立值为0,表示当前还没有发送数据</p> +<p>Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)</p> +<p><strong>第三次握手的数据包</strong></p> +<p>客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052080.png" +loading="lazy" +alt="image-20230410205245006" +></p> +<p>数据包的关键属性如下:</p> +<p>ACK :标志位,表示已经收到记录</p> +<p>Seq = 1 :表示当前已经发送1个数据</p> +<p>Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。</p> +<p>就这样通过了TCP三次握手,建立了连接。开始进行数据交互</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053540.png" +loading="lazy" +alt="image-20230410205305433" +></p> +<p>下面针对数据交互过程的数据包进行一些说明:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053537.png" +loading="lazy" +alt="image-20230410205320467" +></p> +<p>数据包的关键属性说明</p> +<p>Seq: 1</p> +<p>Ack: 1: 说明现在共收到1字节数据</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053985.png" +loading="lazy" +alt="image-20230410205335911" +></p> +<p>Seq: 1<br> +Ack: 951: 说明现在服务端共收到951字节数据</p> +<p>在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053340.png" +loading="lazy" +alt="image-20230410205349152" +></p> +<p>其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。</p> +<h2 id="wireshark分析常用操作">Wireshark分析常用操作 +</h2><p>调整数据包列表中时间戳显示格式。调整方法为View --&gt;Time Display Format --&gt; Date and Time of Day。调整后格式如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102054848.png" +loading="lazy" +alt="image-20230410205401641" +></p>RT-Thread内核宏定义详解(rtdef.h)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/Sun, 09 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/cover.jpg" alt="Featured image of post RT-Thread内核宏定义详解(rtdef.h)" /><h4 id="1rt-thread版本信息">1.RT-Thread版本信息 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread version information */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_VERSION 4 </span><span class="cm">/**&lt; major version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SUBVERSION 1 </span><span class="cm">/**&lt; minor version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_REVISION 1 </span><span class="cm">/**&lt; revise version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread version */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>使用方法:可用于bsp指定RT-Thread版本</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#if (RTTHREAD_VERSION &gt;= RT_VERSION_CHECK(4, 1, 0) */ +</span></span><span class="line"><span class="cl">#define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \ +</span></span><span class="line"><span class="cl"> (minor * 100) + revise) +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2rt-thrad基础数据类型定义">2.RT-Thrad基础数据类型定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread basic data type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_ARCH_DATA_TYPE </span><span class="cm">/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC </span><span class="cm">/* 用于控制是否使用标准C库函数 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">int8_t</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int16_t</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int32_t</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint8_t</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint16_t</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint32_t</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int64_t</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint64_t</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">size_t</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">char</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">short</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">int</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef ARCH_CPU_64BIT </span><span class="cm">/* 判断当前程序运行的CPU架构是否为64位 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* ARCH_CPU_64BIT */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_ARCH_DATA_TYPE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int</span> <span class="kt">rt_bool_t</span><span class="p">;</span> <span class="cm">/**&lt; boolean type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">rt_base_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit CPU related date type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_ubase_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit unsigned CPU related data type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_err_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for error number */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_time_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for time stamp */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_tick_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for tick count */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_flag_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for flags */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_ubase_t</span> <span class="kt">rt_dev_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for device */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_off_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for offset */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* boolean type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TRUE 1 </span><span class="cm">/**&lt; boolean true */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_FALSE 0 </span><span class="cm">/**&lt; boolean fails */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* null pointer definition */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_NULL 0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p><code>rt_base_t</code>:为了使代码可以<strong>在不同的CPU上移植并保持向后兼容性</strong>。<code>long</code>类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用<code>rt_base_t</code>代替<code>long</code>可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)</p> +</li> +<li> +<p><code>rt_err_t</code>:代表<strong>错误码</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_time_t</code>:代表<strong>时间戳</strong>的数据类型,这里使用了<code>rt_uint32_t</code>作为它的别名。<code>rt_uint32_t</code>是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。</p> +</li> +<li> +<p><code>rt_tick_t</code>:代表<strong>系统时钟节拍计数</strong>的数据类型,这里也使用了<code>rt_uint32_t</code>作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对<code>rt_tick_t</code>进行递增操作,从而实现对时间的计数。</p> +</li> +<li> +<p><code>rt_flag_t</code>:代表<strong>标志位</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_dev_t</code>:代表<strong>设备号</strong>的数据类型,这里使用了<code>rt_ubase_t</code>作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。</p> +</li> +<li> +<p><code>rt_off_t</code>:代表<strong>偏移量</strong>的数据类型,这里也使用了之前定义的<code>rt_base_t</code>作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。</p> +</li> +</ul> +<h4 id="3rt-thread基本数据类型的范围">3.RT-Thread基本数据类型的范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of base type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX UINT8_MAX </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX UINT16_MAX </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX UINT32_MAX </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX 0xff </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX 0xffff </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX 0xffffffff </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:此处的<code>UINT8_MAX</code>、<code>UINT16_MAX</code>、<code>UINT32_MAX</code>为编译器预定的宏定义</p> +<h4 id="4rt-thread系统滴答时钟最大计数值">4.RT-Thread系统滴答时钟最大计数值 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TICK_MAX RT_UINT32_MAX </span><span class="cm">/**&lt; Maximum number of tick */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5rt-thread-ipc数据类型范围">5.RT-Thread IPC数据类型范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of ipc type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SEM_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of semaphore .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mutex .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_HOLD_MAX RT_UINT8_MAX </span><span class="cm">/**&lt; Maximum number of mutex .hold */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MB_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mailbox .entry */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MQ_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of message queue .entry */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6rt-thread避免未使用变量警告">6.RT-Thread避免未使用变量警告 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_UNUSED(x) ((void)x) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>**该宏定义表示将变量x强制转换为<code>void</code>类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **</p> +<p>下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。</p> +<p>该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。</p> +<p>在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。</p> +<p>这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* sort code */</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">cmp</span><span class="p">);</span> <span class="c1">// 必须传递一个void*类型参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">b</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就可以避免编译器报“未使用变量a/b”的警告了。</p> +<h4 id="7编译器相关定义">7.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_SECTION(x)</code>:表示<strong>将所修饰的数据/函数放置在指定的section中</strong>,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。</li> +<li><code>RT_USED</code>:表示<strong>告诉编译器保留所修饰的数据/函数</strong>,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。</li> +<li><code>ALIGN(n)</code>:表示<strong>将所修饰的数据/函数按照n字节对齐</strong>,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。</li> +<li><code>RT_WEAK</code>:表示<strong>将所修饰的数据/函数标记为弱引用</strong>,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。</li> +<li><code>rt_inline</code>:表示<strong>将所修饰的函数定义为静态内联函数</strong>,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。</li> +</ul> +<h4 id="8编译器相关定义">8.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* module compiling */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_MODULE +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllimport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllexport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_MODULE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__IAR_SYSTEMS_ICC__) </span><span class="cm">/* for IAR Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) @ x +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __root +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) PRAGMA(data_alignment=n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __weak +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__GNUC__) </span><span class="cm">/* GNU GCC Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* the version of GNU GCC must be greater than 4.x */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__builtin_va_list</span> <span class="n">__gnuc_va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__gnuc_va_list</span> <span class="n">va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define va_start(v,l) __builtin_va_start(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_end(v) __builtin_va_end(v) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_arg(v,l) __builtin_va_arg(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__ADSPBLACKFIN__) </span><span class="cm">/* for VisualDSP++ Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (_MSC_VER) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __declspec(align(n)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TI_COMPILER_VERSION__) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* The way that TI compiler set section is different from other(at least +</span></span></span><span class="line"><span class="cl"><span class="cm"> * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more +</span></span></span><span class="line"><span class="cl"><span class="cm"> * details. */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TASKING__) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used, protect)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((__align(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="cp">#error not supported tool chain +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* __ARMCC_VERSION */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ol> +<li><code>typedef __builtin_va_list __gnuc_va_list</code>: 定义了一个新类型<code>__gnuc_va_list</code>,并使用 <code>__builtin_va_list</code> 进行初始化。<code>__builtin_va_list</code> 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 <code>__builtin_va_list</code> 类型来实现可变参数列表。</li> +<li><code>typedef __gnuc_va_list va_list</code>: 定义了一个名为<code>va_list</code>的新类型,并将其重命名为<code>__gnuc_va_list</code>。</li> +<li><code>#define va_start(v,l) __builtin_va_start(v,l)</code>: 将 <code>va_start()</code> 重命名为 <code>__builtin_va_start()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_start()</code> 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。</li> +<li><code>#define va_end(v) __builtin_va_end(v)</code>: 将 <code>va_end()</code> 重命名为 <code>__builtin_va_end()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_end()</code> 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。</li> +<li><code>#define va_arg(v,l) __builtin_va_arg(v,l)</code>: 将 <code>va_arg()</code> 重命名为 <code>__builtin_va_arg()</code>,并使用 GCC 内建的函数 <code>__builtin_va_arg()</code> 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。</li> +<li><code>#define PRAGMA(x) _Pragma(#x)</code>:将参数<code>x</code>转化为字符串并使用<code>_Pragma()</code>将其作为编译指令执行。<code>_Pragma</code>是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而<code>#pragma</code>则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。</li> +</ol> +<h4 id="9rt-thread错误码定义">9.RT-Thread错误码定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread error code definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_EOK 0 </span><span class="cm">/**&lt; There is no error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ERROR 1 </span><span class="cm">/**&lt; A generic error happens */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ETIMEOUT 2 </span><span class="cm">/**&lt; Timed out */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EFULL 3 </span><span class="cm">/**&lt; The resource is full */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EEMPTY 4 </span><span class="cm">/**&lt; The resource is empty */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOMEM 5 </span><span class="cm">/**&lt; No memory */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOSYS 6 </span><span class="cm">/**&lt; No system */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EBUSY 7 </span><span class="cm">/**&lt; Busy */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EIO 8 </span><span class="cm">/**&lt; IO error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINTR 9 </span><span class="cm">/**&lt; Interrupted system call */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINVAL 10 </span><span class="cm">/**&lt; Invalid argument */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_EOK</code>:表示没有错误。</li> +<li><code>RT_ERROR</code>:表示发生了一般性的错误。</li> +<li><code>RT_ETIMEOUT</code>:表示超时错误。</li> +<li><code>RT_EFULL</code>:表示资源已满。</li> +<li><code>RT_EEMPTY</code>:表示资源为空。</li> +<li><code>RT_ENOMEM</code>:表示内存不足。</li> +<li><code>RT_ENOSYS</code>:表示没有该系统。</li> +<li><code>RT_EBUSY</code>:表示忙碌。</li> +<li><code>RT_EIO</code>:表示输入/输出错误。</li> +<li><code>RT_EINTR</code>:表示中断的系统调用。</li> +<li><code>RT_EINVAL</code>:表示无效的参数。</li> +</ul>【HarmonyOS】小熊派鸿蒙系统搭建https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建" /><h2 id="一bearpi-hm-micro-开发板介绍">一、BearPi-HM Micro 开发板介绍 +</h2><p>BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。</p> +<h2 id="二linux镜像下载">二、Linux镜像下载 +</h2><p>下载官方提供镜像(任选一种方式下载)</p> +<ul> +<li>Ubuntu20.04(大小8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1W0cgtXC5T2bv0lAya7eizA" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA</a> 提取码:1234</li> +<li>Ubuntu18.04(大小4.8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1YIdqlRWRGq_heAfrgQ7EPQ" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ</a> 提取码:1234</li> +</ul> +<h2 id="三bearpi-hm-micro编译环境配置">三、BearPi-HM Micro编译环境配置 +</h2><p>在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置</p> +<h4 id="1首先添加如下镜像源">1.首先添加如下镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /etc/apt/source.list +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 添加中科大源 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2更新镜像源">2.更新镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get update +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3安装依赖库及工具">3.安装依赖库及工具 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">gcc</span> <span class="n">g</span><span class="o">++</span> <span class="n">make</span> <span class="n">zlib</span><span class="o">*</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">e2fsprogs</span> <span class="n">pkg</span><span class="o">-</span><span class="n">config</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">perl</span> <span class="n">bc</span> <span class="n">openssl</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">libelf</span><span class="o">-</span><span class="n">dev</span> <span class="n">libc6</span><span class="o">-</span><span class="n">dev</span><span class="o">-</span><span class="n">amd64</span> <span class="n">binutils</span> <span class="n">binutils</span><span class="o">-</span><span class="n">dev</span> <span class="n">libdwarf</span><span class="o">-</span><span class="n">dev</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">tools</span> <span class="n">mtd</span><span class="o">-</span><span class="n">utils</span> <span class="n">gcc</span><span class="o">-</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabi</span> <span class="n">cpio</span> <span class="n">device</span><span class="o">-</span><span class="n">tree</span><span class="o">-</span><span class="n">compiler</span> <span class="n">net</span><span class="o">-</span><span class="n">tools</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> <span class="n">git</span> <span class="n">vim</span> <span class="n">openjdk</span><span class="o">-</span><span class="mi">11</span><span class="o">-</span><span class="n">jre</span><span class="o">-</span><span class="n">headless</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装hb">4.安装hb +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 安装hb命令 +</span></span><span class="line"><span class="cl">python3 -m pip install --user ohos-build==0.4.3 +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 环境变量配置</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 在.bashrc文件最后一行添加如下代码,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/.</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5测试hb是否安装成功">5.测试hb是否安装成功 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb -h +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071818214.png" +loading="lazy" +alt="image-20230407181805793" +></p> +<h2 id="四安装mkimage工具">四、安装mkimage工具 +</h2><p>首先解释这个工具的用途:<strong>用来制作不压缩或者压缩的多种可启动映象文件。</strong></p> +<h4 id="1新建tools目录">1.新建tools目录 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">~/</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2下载mkimagestm32工具到tools目录并复制到homebearpitools目录下">2.下载mkimage.stm32工具到<code>~/tools</code>目录,并复制到/home/bearpi/tools/目录下 +</h4><ul> +<li><a class="link" href="https://pan.baidu.com/share/init?surl=T2O8luJ0-8g5ZZYdOvWfqQ" target="_blank" rel="noopener" +>mkimage.stm32下载地址</a> 提取码:1234</li> +</ul> +<h4 id="3修改mkimagestm32文件权限">3.修改mkimage.stm32文件权限 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chmod</span> <span class="mi">777</span> <span class="o">~/</span><span class="n">tools</span><span class="o">/</span><span class="n">mkimage</span><span class="o">.</span><span class="n">stm32</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4设置环境变量">4.设置环境变量 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 将下面的代码拷贝至.bashrc文件最后,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/</span><span class="n">tools</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="五bearpi镜像导入vmware">五、bearpi镜像导入VMware +</h2><p>准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-&gt;打开(O),选择我们Linux镜像中的<code>BearPi-HM_Micro_Ubuntu.ovf</code>文件,等待镜像文件的导入,开始登录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">账户:bearpi +</span></span><span class="line"><span class="cl">密码:bearpi +</span></span></code></pre></td></tr></table> +</div> +</div><p>首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-&gt;设置-&gt;网络适配器-&gt;NAT模式</p> +<p>此时打开一个终端,输入ifconfig查看ip</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071852103.png" +loading="lazy" +alt="image-20230407185206621" +></p> +<h2 id="六源码获取">六、源码获取 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mkdir project &amp;&amp; cd project +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七编译代码">七、编译代码 +</h2><p>首先进入到项目文件夹中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi/project/bearpi-hm_micro_small/ +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行如下命令(普通用户模式终端下):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb set +</span></span></code></pre></td></tr></table> +</div> +</div><p>出现<code>[OHOS INFO] Input code path: </code>提示信息后再输入<code>.</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071902001.png" +loading="lazy" +alt="image-20230407190200859" +></p> +<p>我们选择<code>bearpi-hm_micro</code>后回车</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071904137.png" +loading="lazy" +alt="image-20230407190426957" +></p> +<p>输入下面的命令,等待下载程序完成</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb build -t notest --tee -f +</span></span></code></pre></td></tr></table> +</div> +</div><p>当出现<code>build success</code>时,即代表编译成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071916323.png" +loading="lazy" +alt="image-20230407191628183" +></p> +<h2 id="八查看编译出的固件位置">八、查看编译出的固件位置 +</h2><p>当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: <code>/home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro</code> 其中有以下文件是后面烧录系统需要使用的。</p> +<ul> +<li>OHOS_Image.stm32:系统镜像文件</li> +<li>rootfs_vfat.img:根文件系统</li> +<li>userfs_vfat.img:用户文件系统</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071919790.png" +loading="lazy" +alt="image-20230407191938678" +></p> +<p>我们将这三个文件复制到该目录下:<code>/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/</code>,方便后续烧录系统使用</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="n">OHOS_Image</span><span class="o">.</span><span class="n">stm32</span> <span class="n">rootfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="n">userfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">bearpi</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">bearpi</span><span class="o">-</span><span class="n">hm_micro_small</span><span class="o">/</span><span class="n">applications</span><span class="o">/</span><span class="n">BearPi</span><span class="o">/</span><span class="n">BearPi</span><span class="o">-</span><span class="n">HM_Micro</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">download_img</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071929824.png" +loading="lazy" +alt="image-20230407192926584" +></p> +<h2 id="九固件烧录">九、固件烧录 +</h2><h4 id="1准备工作">1.准备工作 +</h4><ul> +<li><a class="link" href="https://www.wch.cn/downloads/CH341SER_EXE.html" target="_blank" rel="noopener" +>CH340驱动</a></li> +<li><a class="link" href="https://www.st.com/en/development-tools/stm32cubeprog.html#get-software" target="_blank" rel="noopener" +>STM32CubeProgramme(v2.4.0+)</a></li> +</ul> +<h4 id="2连接开发板">2.连接开发板 +</h4><p>首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:<a class="link" href="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/" target="_blank" rel="noopener" +>【Linux系统开发】Ubuntu配置SFTP服务</a>)</p> +<p>当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。</p> +<p>我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111834424.png" +loading="lazy" +alt="image-20230411183456029" +></p> +<h4 id="3镜像烧录">3.镜像烧录 +</h4><ul> +<li> +<p>首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。</p> +</li> +<li> +<p>打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。</p> +</li> +<li> +<p>点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:<code>Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv</code>)。</p> +</li> +<li> +<p>点击Browse按钮,然后选择工程源码下的烧录镜像路径</p> +</li> +<li> +<p>点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111935608.png" +loading="lazy" +alt="image-20230411193521444" +></p> +<h4 id="4启动系统">4.启动系统 +</h4><p>将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111940183.jpg" +loading="lazy" +alt="3" +></p>【Linux系统开发】Ubuntu配置SFTP服务https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover.jpg" alt="Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务" /><h2 id="sftp介绍">SFTP介绍 +</h2><p>SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)</p> +<h2 id="安装步骤">安装步骤 +</h2><h4 id="1目标">1.目标: +</h4><p>在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。</p> +<h4 id="2查看ubuntu系统信息">2.查看Ubuntu系统信息 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071010234.png" +loading="lazy" +alt="image-20230407101026858" +></p> +<h4 id="3检查是否已安装sftp">3.检查是否已安装SFTP +</h4><p>在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071011398.png" +loading="lazy" +alt="image-20230407101132327" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">client</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">client</span> +</span></span><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">server</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。</p> +<h4 id="4新建用户组sftp-users并新建用户sftp">4.新建用户组SFTP-users,并新建用户SFTP +</h4><p>为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">adduser</span> <span class="nf">sftp</span> <span class="p">(</span><span class="err">这部分会让你新建用户组信息,建议最好截图保存下</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5给sftp赋权并新建用户组ssh-users">5.给SFTP赋权并新建用户组SSH-users +</h4><p>将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">G</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="nb">false</span> <span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">a</span> <span class="o">-</span><span class="n">G</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">bbc2005</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6创建并设置sftp用户目录">6.创建并设置SFTP用户目录 +</h4><p>为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chown</span> <span class="nl">yifang</span><span class="p">:</span><span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chmod</span> <span class="mi">770</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="7修改ssh配置文件">7.修改SSH配置文件 +</h4><p>在sshd_config文件的最后添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssh</span><span class="o">/</span><span class="n">sshd_config</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">AllowGroups</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">Match</span> <span class="n">Group</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">ChrootDirectory</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">AllowTcpForwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"><span class="n">X11Forwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">ForceCommand</span> <span class="n">internal</span><span class="o">-</span><span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些内容的意思是:</p> +<ul> +<li>只允许ssh-users和SFTP-users通过SSH访问系统;</li> +<li>针对SFTP-users用户,增加一些额外的设置: +<ul> +<li>将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);</li> +<li>禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。</li> +<li>如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。</li> +</ul> +</li> +</ul> +<h4 id="8sftp客户端验证">8.SFTP客户端验证 +</h4><p>首先将虚拟机重启:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">reboot</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。</p> +<p>查看ubuntu网络ip地址</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ifconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071038531.png" +loading="lazy" +alt="image-20230407103802472" +>zhe</p> +<p>这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考<a class="link" href="https://blog.devyi.com/archives/418/" target="_blank" rel="noopener" +>RaiDrive—将网盘映射为磁盘</a>)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071044734.png" +loading="lazy" +alt="image-20230407104441660" +></p> +<p>此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071046125.png" +loading="lazy" +alt="image-20230407104643007" +></p>【资讯】汇总一些嵌入式相关的公司https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/<img src="https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/cover.jpg" alt="Featured image of post 【资讯】汇总一些嵌入式相关的公司" /><blockquote> +<p>来源:https://zhuanlan.zhihu.com/p/585079427</p> +</blockquote> +<h2 id="1芯片行业">1.芯片行业 +</h2><p>目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。</p> +<p>代表性公司:</p> +<p>(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等</p> +<p>(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等</p> +<h2 id="2人工智能相关行业">2.人工智能相关行业 +</h2><p>(1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。</p> +<p>(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等</p> +<h2 id="3消费电子行业">3.消费电子行业 +</h2><p>消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等</p> +<h2 id="4传统汽车行业">4.传统汽车行业 +</h2><p>传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等</p> +<h2 id="5国企和军工">5.国企和军工 +</h2><p>国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。</p> +<h2 id="6传统电子电器类">6.传统电子电器类 +</h2><p>这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等</p> +<h2 id="7网络及通信设备">7.网络及通信设备 +</h2><p>主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等</p>【经验分享】ARM常用汇编指令https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/Wed, 29 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/cover.jpg" alt="Featured image of post 【经验分享】ARM常用汇编指令" /><h1 id="arm常用汇编指令">ARM常用汇编指令 +</h1><table> +<thead> +<tr> +<th>指令名称</th> +<th>作用</th> +</tr> +</thead> +<tbody> +<tr> +<td>EQU</td> +<td>给数字常量设置一个符号名,相当于C语言中的define</td> +</tr> +<tr> +<td>AREA</td> +<td>汇编一个新的代码段或者数据段</td> +</tr> +<tr> +<td>SPACE</td> +<td>分配内存空间</td> +</tr> +<tr> +<td>PRESERVE8</td> +<td>当前文件栈需要按照8字节对齐</td> +</tr> +<tr> +<td>EXPORT</td> +<td>声明一个符号具有全局属性,可被外部文件使用</td> +</tr> +<tr> +<td>DCD</td> +<td>以字为单位分配内存,要求4字节对齐,并要求初始化这些内存</td> +</tr> +<tr> +<td>PROC</td> +<td>定义子程序,与ENDP成对使用,表示子程序结束</td> +</tr> +<tr> +<td>WEAK</td> +<td>弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>IMPORT</td> +<td>声明标号来自外部文件,与C语言的EXETERN关键字类似</td> +</tr> +<tr> +<td>B</td> +<td>跳转到一个标号</td> +</tr> +<tr> +<td>ALIGN</td> +<td>编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>END</td> +<td>到达文件的末尾,文件结束</td> +</tr> +<tr> +<td>IF,ELSE,ENDIF</td> +<td>汇编条件分支语句,与C语言的if else类似</td> +</tr> +<tr> +<td>MRS</td> +<td>加载特殊功能寄存器的值到特殊功能寄存器</td> +</tr> +<tr> +<td>CBZ</td> +<td>比较,如果结果为0则转移</td> +</tr> +<tr> +<td>CBNZ</td> +<td>比较,如果结果非0则转移</td> +</tr> +<tr> +<td>LDR</td> +<td>从存储器中加载字到一个寄存器中</td> +</tr> +<tr> +<td>LDR[伪指令]</td> +<td>加载一个立即数或者一个地址到一个寄存器中。</td> +</tr> +<tr> +<td>LDRH</td> +<td>从存储器中加载半字到一个寄存器中</td> +</tr> +<tr> +<td>LDRB</td> +<td>从存储器中加载字节到一个寄存器中</td> +</tr> +<tr> +<td>STR</td> +<td>把一个寄存器按字节存储到存储器中</td> +</tr> +<tr> +<td>STRH</td> +<td>把一个寄存器的低半字存储到存储器中</td> +</tr> +<tr> +<td>STRB</td> +<td>把一个寄存器的低字节存储到存储器中</td> +</tr> +<tr> +<td>LDMIA</td> +<td>加载多个字,并且在加载后自增基址寄存器</td> +</tr> +<tr> +<td>STMIA</td> +<td>存储多个字,并且在存储后自增基址寄存器</td> +</tr> +<tr> +<td>ORR</td> +<td>按位或</td> +</tr> +<tr> +<td>BX</td> +<td>直接跳转到由寄存器给定的地址</td> +</tr> +<tr> +<td>BL</td> +<td>跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR</td> +</tr> +<tr> +<td>BLX</td> +<td>跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错</td> +</tr> +</tbody> +</table>【Git版本控制】Git命令详解https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/Fri, 17 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 【Git版本控制】Git命令详解" /><h2 id="前言">前言 +</h2><p>Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 <strong>回撤</strong>这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而<strong>版本管理工具能记录每次的修改</strong>,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。</p> +<p>下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。</p> +<h2 id="展示帮助信息">展示帮助信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git help -g +</span></span></code></pre></td></tr></table> +</div> +</div><p>The command output as below:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">The common Git guides are: +</span></span><span class="line"><span class="cl"> attributes Defining attributes per path +</span></span><span class="line"><span class="cl"> cli Git command-line interface and conventions +</span></span><span class="line"><span class="cl"> core-tutorial A Git core tutorial for developers +</span></span><span class="line"><span class="cl"> cvs-migration Git for CVS users +</span></span><span class="line"><span class="cl"> diffcore Tweaking diff output +</span></span><span class="line"><span class="cl"> everyday A useful minimum set of commands for Everyday Git +</span></span><span class="line"><span class="cl"> glossary A Git Glossary +</span></span><span class="line"><span class="cl"> hooks Hooks used by Git +</span></span><span class="line"><span class="cl"> ignore Specifies intentionally untracked files to ignore +</span></span><span class="line"><span class="cl"> modules Defining submodule properties +</span></span><span class="line"><span class="cl"> namespaces Git namespaces +</span></span><span class="line"><span class="cl"> repository-layout Git Repository Layout +</span></span><span class="line"><span class="cl"> revisions Specifying revisions and ranges for Git +</span></span><span class="line"><span class="cl"> tutorial A tutorial introduction to Git +</span></span><span class="line"><span class="cl"> tutorial-2 A tutorial introduction to Git: part two +</span></span><span class="line"><span class="cl"> workflows An overview of recommended workflows with Git +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">&#39;git help -a&#39; and &#39;git help -g&#39; list available subcommands and some concept guides. See &#39;git help &lt;command&gt;&#39; or &#39;git help &lt;concept&gt;&#39; to read about a specific subcommand or concept. +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到远程仓库的状态">回到远程仓库的状态 +</h2><p>抛弃本地所有的修改,回到远程仓库的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch --all &amp;&amp; git reset --hard origin/master +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重设第一个-commit">重设第一个 commit +</h2><p>也就是把所有的改动都重新放回工作区,并<strong>清空所有的 commit</strong>,这样就可以重新提交第一个 commit 了</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-ref -d HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看冲突文件列表">查看冲突文件列表 +</h2><p>展示工作区的冲突文件列表</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --name-only --diff-filter=U +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示工作区和暂存区的不同">展示工作区和暂存区的不同 +</h2><p>输出<strong>工作区</strong>和<strong>暂存区</strong>的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff +</span></span></code></pre></td></tr></table> +</div> +</div><p>还可以展示本地仓库中任意两个 commit 之间的文件变动:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff &lt;commit-id&gt; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区和最近版本的不同">展示暂存区和最近版本的不同 +</h2><p>输出<strong>暂存区</strong>和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --cached +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区工作区和最近版本的不同">展示暂存区、工作区和最近版本的不同 +</h2><p>输出<strong>工作区</strong>、<strong>暂存区</strong> 和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="快速切换到上一个分支">快速切换到上一个分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout - +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除已经合并到-master-的分支">删除已经合并到 master 的分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch --merged master | grep -v &#39;^\*\| master&#39; | xargs -n 1 git branch -d +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示本地分支关联远程仓库的情况">展示本地分支关联远程仓库的情况 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -vv +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="关联远程分支">关联远程分支 +</h2><p>关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -u origin/mybranch +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者在 push 时加上 -u 参数</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin/mybranch -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程分支">列出所有远程分支 +</h2><p>-r 参数相当于:remote</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -r +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出本地和远程分支">列出本地和远程分支 +</h2><p>-a 参数相当于:all</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -a +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看远程分支和本地分支的对应关系">查看远程分支和本地分支的对应关系 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote show origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="远程删除了分支本地也想删除">远程删除了分支本地也想删除 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote prune origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="创建并切换到本地分支">创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程分支中创建并切换到本地分支">从远程分支中创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; origin/&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地分支">删除本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -d &lt;local-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程分支">删除远程分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete &lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin :&lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重命名本地分支">重命名本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -m &lt;new-branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签">查看标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag +</span></span></code></pre></td></tr></table> +</div> +</div><p>展示当前分支的最近的 tag</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git describe --tags --abbrev=0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签详细信息">查看标签详细信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -ln +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="本地创建标签">本地创建标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag &lt;version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ git tag -a &lt;version-number&gt; -m &#34;v1.0 发布(描述)&#34; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="推送标签到远程仓库">推送标签到远程仓库 +</h2><p>首先要保证本地创建好了标签才可以推送标签到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin &lt;local-version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>一次性推送所有标签,同步到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --tags +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地标签">删除本地标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -d &lt;tag-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程标签">删除远程标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete tag &lt;tagname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="切回到某个标签">切回到某个标签 +</h2><p>一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b branch_name tag_name +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="放弃工作区的修改">放弃工作区的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>放弃所有修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout . +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="恢复删除的文件">恢复删除的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rev-list -n 1 HEAD -- &lt;file_path&gt; #得到 deleting_commit +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git checkout &lt;deleting_commit&gt;^ -- &lt;file_path&gt; #回到删除文件 deleting_commit 之前的状态 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以新增一个-commit-的方式还原某一个-commit-的修改">以新增一个 commit 的方式还原某一个 commit 的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git revert &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-commit-的状态并删除后面的-commit">回到某个 commit 的状态,并删除后面的 commit +</h2><p>和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;commit-id&gt; #默认就是-mixed参数。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --hard &lt;commit-id&gt; #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改上一个-commit-的描述">修改上一个 commit 的描述 +</h2><p>如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看-commit-历史">查看 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看某段代码是谁写的">查看某段代码是谁写的 +</h2><p>blame 的意思为‘责怪’,你懂的。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git blame &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="显示本地更新过-head-的-git-命令记录">显示本地更新过 HEAD 的 git 命令记录 +</h2><p>每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reflog +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改作者名">修改作者名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend --author=&#39;Author Name &lt;email@address.com&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改远程仓库的-url">修改远程仓库的 url +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote set-url origin &lt;URL&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="增加远程仓库">增加远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote add origin &lt;remote-url&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程仓库">列出所有远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看两个星期内的改动">查看两个星期内的改动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git whatchanged --since=&#39;2 weeks ago&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把-a-分支的某一个-commit放到-b-分支上">把 A 分支的某一个 commit,放到 B 分支上 +</h2><p>这个过程需要 cherry-pick 命令,<a class="link" href="http://sg552.iteye.com/blog/1300713#bc2367928" target="_blank" rel="noopener" +>参考</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;branch-name&gt; &amp;&amp; git cherry-pick &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="给-git-命令起别名">给 git 命令起别名 +</h2><p>简化命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global alias.&lt;handle&gt; &lt;command&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">比如:git status 改成 git st,这样可以简化命令 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git config --global alias.st status +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="存储当前的修改但不用提交-commit">存储当前的修改,但不用提交 commit +</h2><p>详解可以参考<a class="link" href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137602359178794d966923e5c4134bc8bf98dfb03aea3000" target="_blank" rel="noopener" +>廖雪峰老师的 git 教程</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="保存当前状态包括-untracked-的文件">保存当前状态,包括 untracked 的文件 +</h2><p>untracked 文件:新建的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-stashes">展示所有 stashes +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash list +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-stash-的状态">回到某个 stash 的状态 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash apply &lt;stash@{n}&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到最后一个-stash-的状态并删除这个-stash">回到最后一个 stash 的状态,并删除这个 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash pop +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除所有的-stash">删除所有的 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash clear +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从-stash-中拿出某个文件的修改">从 stash 中拿出某个文件的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;stash@{n}&gt; -- &lt;file-path&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-tracked-的文件">展示所有 tracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files -t +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-untracked-的文件">展示所有 untracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有忽略的文件">展示所有忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others -i --exclude-standard +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的文件">强制删除 untracked 的文件 +</h2><p>可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,<strong>注意两点</strong>:</p> +<ol> +<li>clean 后,删除的文件无法找回</li> +<li>不会影响 tracked 的文件的改动,只会删除 untracked 的文件</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;file-name&gt; -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的目录">强制删除 untracked 的目录 +</h2><p>可以用来删除新建的目录,<strong>注意</strong>:这个命令也可以用来删除 untracked 的文件。详情见上一条</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;directory-name&gt; -df +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示简化的-commit-历史">展示简化的 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --pretty=oneline --graph --decorate --all +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把某一个分支导出成一个文件">把某一个分支导出成一个文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git bundle create &lt;file&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从包中导入分支">从包中导入分支 +</h2><p>新建一个分支,分支内容就是上面 git bundle create 命令导出的内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone repo.bundle &lt;repo-dir&gt; -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="执行-rebase-之前自动-stash">执行 rebase 之前自动 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rebase --autostash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程仓库根据-id拉下某一状态到本地分支">从远程仓库根据 ID,拉下某一状态,到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch origin pull/&lt;id&gt;/head:&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="详细展示一行中的修改">详细展示一行中的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --word-diff +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="清除-gitignore-文件中记录的文件">清除 gitignore 文件中记录的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean -X -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-alias-和-configs">展示所有 alias 和 configs +</h2><p><strong>注意:</strong> config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --local --list (当前目录) +</span></span><span class="line"><span class="cl">git config --global --list (全局) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示忽略的文件">展示忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git status --ignored +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="commit-历史中显示-branch1-有的但是-branch2-没有-commit">commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log Branch1 ^Branch2 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中显示-gpg-签名">在 commit log 中显示 GPG 签名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --show-signature +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除全局设置">删除全局设置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global --unset &lt;entry-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="新建并切换到新分支上同时这个分支没有任何-commit">新建并切换到新分支上,同时这个分支没有任何 commit +</h2><p>相当于保存修改,但是重写 commit 历史</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout --orphan &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示任意分支某一文件的内容">展示任意分支某一文件的内容 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git show &lt;branch-name&gt;:&lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-下来指定的单一分支">clone 下来指定的单一分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone -b &lt;branch-name&gt; --single-branch https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-最新一次提交">clone 最新一次提交 +</h2><p>只会 clone 最近一次提交,将减少 clone 时间</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --depth=1 https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略某个文件的改动">忽略某个文件的改动 +</h2><p>关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><p>恢复 track 指定文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --no-assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略文件的权限变化">忽略文件的权限变化 +</h2><p>不再将文件的权限变化视作改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config core.fileMode false +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以最后提交的顺序列出所有-git-分支">以最后提交的顺序列出所有 Git 分支 +</h2><p>最新的放在最上面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git for-each-ref --sort=-committerdate --format=&#39;%(refname:short)&#39; refs/heads/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中查找相关内容">在 commit log 中查找相关内容 +</h2><p>通过 grep 查找,given-text:所需要查找的字段</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --all --grep=&#39;&lt;given-text&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把暂存区的指定-file-放到工作区中">把暂存区的指定 file 放到工作区中 +</h2><p>不添加参数,默认是 -mixed</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制推送">强制推送 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push -f &lt;remote-name&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p>瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/Mon, 22 Aug 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/<img src="https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/cover.jpg" alt="Featured image of post 瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包" /><h4 id="一创建工程选择segger_rtt软件包">一、创建工程,选择SEGGER_RTT软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/015bb29dd26648570d03e65cd419f972.png" +loading="lazy" +alt="image-20221003133030692" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fb34abd8ec95bf35f09fb3bcde1f5d1d.png" +loading="lazy" +alt="image-20221003133219108" +></p> +<h4 id="2添加jlinkrtt初始化函数-路径rt-threadsrckservicec-">2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ] +</h4><p>在<code>rt_console_set_device</code>前调用<code>rt_hw_jlink_rtt_init</code>初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/492ff3b5ab1bf24e62a4380f3d47bf29.png" +loading="lazy" +alt="image-20221003133721333" +></p> +<h4 id="3控制台对接上jlinkrtt">3、控制台对接上jlinkRtt +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rtconfg.h +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// 修改RT_CONSOLE_DEVICE_NAME为空 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/img_convert/a4101391c61fad4add9376b4ebcd71e9.png" +loading="lazy" +alt="image-20221003134935152" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">shell</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="nl">D</span><span class="p">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">components</span><span class="err">\</span><span class="n">finsh</span><span class="err">\</span><span class="n">shell</span><span class="p">.</span><span class="n">c</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 1、首先添加以下头文件 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT_Conf.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 2、修改finsh_getchar */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">finsh_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_DEVICE +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">char</span> <span class="n">ch</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_POSIX_STDIO +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span><span class="p">(</span><span class="nf">read</span><span class="p">(</span><span class="n">STDIN_FILENO</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="cm">/* EOF */</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">rt_device_t</span> <span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_ASSERT</span><span class="p">(</span><span class="n">shell</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="nf">rt_device_read</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">rx_sem</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span> <span class="o">!=</span> <span class="n">device</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_POSIX_STDIO */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_DEVICE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">src</span><span class="err">\</span><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">RT_WEAK</span> <span class="kt">void</span> <span class="nf">rt_hw_console_output</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* empty console output */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">str</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="sc">&#39;\n&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SEGGER_RTT_printf</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s">&#34;%s&#34;</span><span class="p">,</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">RTM_EXPORT</span><span class="p">(</span><span class="n">rt_hw_console_output</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4实验效果">4、实验效果 +</h4><p>首先确保已经下载好<code>J-Link RTT Viewer</code>,直接去<a class="link" href="https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/" target="_blank" rel="noopener" +>官网</a>下载最新版本即可</p> +<p>然后编译和下载工程,注意下载方式为<code>J-Link</code></p> +<p>双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看<code>_SEGGER_RTT</code>变量地址(全局搜索即可,找到.bss._SEGGER_RTT)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/608cb3d791c683d7886a92eef5ae848f.png" +loading="lazy" +alt="image-20221003140449806" +></p> +<p>打开<code>J-Link RTT Viewer</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5e3d4a57e4a6b55dd62f61b5d6577105.png" +loading="lazy" +alt="image-20221003140736161" +></p> +<p>此时就可以正常使用segger_rtt了!</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/d09d8a0f28e2c45542199eb982dfed6e.png" +loading="lazy" +alt="image-20221003140911791" +></p>【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Fri, 29 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/cover.jpg" alt="Featured image of post 【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制" /><h4 id="一了解tortoisegit">一、了解TortoiseGit +</h4><p>TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。</p> +<p>由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。</p> +<p>TortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。</p> +<p>它是在<a class="link" href="https://www.gnu.org/licenses/gpl-2.0" target="_blank" rel="noopener" +>GPL</a>下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。</p> +<h4 id="二安装giit及tortoisegit">二、安装GIit及TortoiseGit +</h4><ul> +<li>Git下载官网: <a class="link" href="https://gitforwindows.org/index.html" target="_blank" rel="noopener" +>https://gitforwindows.org/index.html</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4a21fd0a6bd1453ba31032ce73c67d73.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>TortoiseGit下载官网:<a class="link" href="https://tortoisegit.org/download/" target="_blank" rel="noopener" +>https://tortoisegit.org/download/</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ba9793defe4baa02684e53320b79bde4.png" +loading="lazy" +alt="image-20220720090147944" +></p> +<ul> +<li>同时下载语言包</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b9cb668ce4c7a1ba2cda1a6bab5a0a76.png" +loading="lazy" +></p> +<p>当然这里也有百度网盘链接,也可点击下方链接进行下载</p> +<p>链接:<a class="link" href="https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs</a> +提取码:dzbs</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/db691a46832cc291932ff63fcc3e9a74.png" +loading="lazy" +alt="image-20220720090721507" +></p> +<h4 id="三tortoisegit配置">三、TortoiseGit配置 +</h4><p>完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67fb3421c49f0c5e90e76fa3c04c9b71.png" +loading="lazy" +alt="image-20220720091049882" +></p> +<p>这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/853a58d535b9e2370949ccb7917b80b5.png" +loading="lazy" +alt="image-20220720091218159" +></p> +<p>配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/e70b76490f6f5cfc699d79df3968e1fe.png" +loading="lazy" +alt="image-20220720091439829" +></p> +<p>点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[credential] +</span></span><span class="line"><span class="cl"> helper = store +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成后保存,关闭记事本,确定即可。</p> +<p>  则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。</p> +<p>  如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。</p> +<h4 id="四添加github-ssh-keys及密钥上传">四、添加GitHub SSH Keys及密钥上传 +</h4><p>首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\TortoiseGit\bin\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/33d7c521e31040d4921e11ab1b12bd74.png" +loading="lazy" +alt="image-20220720092721281" +> +<img src="https://img-blog.csdnimg.cn/img_convert/3f27c4682dc82b0bd0f3ef5c89a1df7e.png" +loading="lazy" +alt="image-20220720093308539" +></p> +<p>然后复制下方公钥,</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2a5f6daf15cc2e9935764b207b726cf7.png" +loading="lazy" +alt="image-20220720093236525" +></p> +<p>打开github,完成下图操作:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/52cf49261a89b3186083dfb7240ea8dd.png" +loading="lazy" +alt="image-20220815182247315" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/1db55857a0118c8cabc02f9a5c4bb19b.png" +loading="lazy" +alt="image-20220815182404425" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b406ac32656957356de898117c6bb17f.png" +loading="lazy" +alt="image-20220815182541297" +></p> +<h4 id="五使用tortoisegit提交代码到远端仓库">五、使用TortoiseGit提交代码到远端仓库 +</h4><p>在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/846315f99c2e767666f7be83437e4969.png" +loading="lazy" +alt="image-20220815185026555" +></p> +<p>鼠标右键可以看到选项<code>Git在这里创建版本库</code>,点击创建版本库</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bcb80e2391a690906240fd0d1b197e7a.png" +loading="lazy" +alt="image-20220815185825412" +></p> +<p>鼠标右键打开TortoiseGit-&gt;设置(Settings)-&gt;Git-&gt;远端(Remote),进行如下配置</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a1f9b059fb25b079395ad2588d51c0c5.png" +loading="lazy" +alt="image-20220815191405483" +></p> +<p>此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9c4fbf6ee5360e497644e6330255a278.png" +loading="lazy" +alt="image-20220815190637369" +></p> +<p>我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">正常的:绿色的对号 +</span></span><span class="line"><span class="cl">被修改过的:红色感叹号 +</span></span><span class="line"><span class="cl">新添加的:蓝色的加号 +</span></span><span class="line"><span class="cl">未受控的(无版本控制的):蓝色的问号 +</span></span><span class="line"><span class="cl">忽略不受控的:灰色的减号 +</span></span><span class="line"><span class="cl">删除的:红色的x号 +</span></span><span class="line"><span class="cl">有冲突的:黄色的感叹号 +</span></span></code></pre></td></tr></table> +</div> +</div><p>鼠标右键添加文件</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f146752e79d7bd6a4e9287e2c32ad3c1.png" +loading="lazy" +alt="image-20220815191829438" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/50b75011172011ae724d81bd921f8fdc.png" +loading="lazy" +alt="image-20220815191933736" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a9acdcdf6d14730de5e91df7564f65f8.png" +loading="lazy" +alt="image-20220815192002035" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/6439911282c3c25bde45fa033f3a58b3.png" +loading="lazy" +alt="image-20220815192321480" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/73d32ab54fc9914ea2d1a967c5b91065.png" +loading="lazy" +alt="image-20220815193032859" +></p> +<p><strong><code>注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次</code></strong></p> +<p>总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)</p> +<p><em><strong><code>添加-&gt;提交-&gt;拉取-&gt;推送</code></strong></em></p> +<p>那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!</p>x210开发板根目录文件系统构建https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/Thu, 28 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/cover.jpg" alt="Featured image of post x210开发板根目录文件系统构建" /><h2 id="一开发板配置">一、开发板配置 +</h2><p>(使用secureCRT) +首先确保开发板完成以下配置:</p> +<p>主机IP: +<code>set ipaddr192.168.1.10</code> +服务器IP: +<code>set serverip 192.168.1.141</code> +网关: +<code>set gatewayip 192.168.1.1</code> +子网掩码: +<code>set netmask 255.255.255.0</code> +内核驱动设置: +<code>set bootcmd 'tftp 30008000 zImage; bootm 30008000'</code> +bootargs配置: +<code>set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200</code></p> +<p>最后输入save保存一下,这样开发板的网络和内核配置就设置好了</p> +<h2 id="二了解rootfs">二、了解rootfs +</h2><p>rootfs的两种表现形式: +1、nfs方式启动的文件夹形式的rootfs(主机)</p> +<p>2、用来烧录的镜像形式rootfs(开发板)</p> +<h2 id="三虚拟机文件配置">三、虚拟机文件配置 +</h2><h4 id="1目录配置">1.目录配置 +</h4><p>首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: +<code>rootfs x210_bsp</code></p> +<p>这时候我们需要知道这两个文件夹下有什么:</p> +<blockquote> +<ul> +<li>x210_bsp:用于uboot烧录和配置</li> +<li>rootfs:用于挂载开发板根文件系统</li> +</ul> +</blockquote> +<h4 id="2x210_bsp配置">2.x210_bsp配置 +</h4><p>首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压</p> +<p><img src="https://img-blog.csdnimg.cn/b4f56856fa1447b6b49ea43313bc141a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用</p> +<h4 id="3rootfs配置">3.rootfs配置 +</h4><p>首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压</p> +<p><img src="https://img-blog.csdnimg.cn/87600bf5cbf44ac3a94db3bc7bd01d78.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件</p> +<h4 id="4make-menuconfig">4.make menuconfig +</h4><p>进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单</p> +<blockquote> +<p>这里我们按下面操作完成网络配置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[*]Networking support ---&gt; +</span></span><span class="line"><span class="cl"> Networking options ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/a33a8e4e25bc4335b263cdbc59bd79a6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>网络文件系统设置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">File systems ---&gt; +</span></span><span class="line"><span class="cl"> [*]Networking File Systems ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>有需要把开发板作为服务器端的也可以选择把<code>NFS server support</code>设置打开,这里我们仅实验客户端</p> +<p><img src="https://img-blog.csdnimg.cn/ce11d76876fd463db53915dffde15776.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上配置结束后输入命令<code>make</code>编译,至此开发板uboot的网络和文件系统部分配置结束。</p> +<h2 id="四busybox的移植实战">四、busybox的移植实战 +</h2><h4 id="1了解busybox">1、了解busybox +</h4><blockquote> +<p>busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。</p> +</blockquote> +<h4 id="2busybox源码获取">2、busybox源码获取 +</h4><p><a class="link" href="http://www.busybox.net/" target="_blank" rel="noopener" +>busybox官网</a></p> +<p><code>注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)</code></p> +<h4 id="3busybox配置">3、busybox配置 +</h4><p>(1)修改Makefile</p> +<p>首先进入<code>~/rootfs/x210_rootfs/busybox-1.24.1</code>目录下</p> +<p>输入命令<code>vi Makefile</code>进入脚本进行以下修改</p> +<p>173行:<code>CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-</code> +<code>注意:此处的交叉编译链需要对照自己电脑的交叉编译链</code> +191行:<code>ARCH=arm</code></p> +<p><img src="https://img-blog.csdnimg.cn/988e15e86dde4807aa26011e6686bc6f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>(2)make menuconfig配置</p> +<p>Tip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 +因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。</p> +<p>make menuconfig</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Settings</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="n">Build</span> <span class="n">Options</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Build</span> <span class="n">BusyBox</span> <span class="n">as</span> <span class="n">a</span> <span class="k">static</span> <span class="n">binary</span><span class="p">(</span><span class="n">no</span> <span class="n">shared</span> <span class="n">libs</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Library</span> <span class="n">Tuning</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">vi</span><span class="o">-</span><span class="n">style</span> <span class="n">line</span> <span class="n">editing</span> <span class="n">commands</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Fancy</span> <span class="n">shell</span> <span class="n">prompts</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">Module</span> <span class="n">Utilities</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span> <span class="p">]</span><span class="n">Simplified</span> <span class="n">modutils</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">insmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">rmmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">lsmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">modprobe</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">depmod</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">System</span> <span class="n">Utilities</span><span class="o">---&gt;</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">mdev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">mdev</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">subdirs</span><span class="o">/</span><span class="n">symlinks</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">regular</span> <span class="n">expressions</span> <span class="n">substitutions</span> <span class="n">when</span> <span class="n">renaming</span> <span class="n">dev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">command</span> <span class="n">execution</span> <span class="n">at</span> <span class="n">device</span> <span class="n">addition</span><span class="o">/</span><span class="n">removal</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">loading</span> <span class="n">of</span> <span class="n">firmwares</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>大家学习使用的时候跟着上面的进行配置即可 +配置完成后,输入以下命令: +<code>make -j4</code> (4代表我主机的内核数) +无报错继续下一步: +make install</p> +<blockquote> +<p>解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装</p> +</blockquote> +<p>(3)设置busybox安装路径</p> +<ul> +<li><code>make menuconfig</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Busybox Settings ---&gt; +</span></span><span class="line"><span class="cl"> Installation Options (&#34;make install&#34; behavior) ---&gt; +</span></span><span class="line"><span class="cl"> (./)BusyBox installation prefix) //这里设置安装路径 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cf7de167425b47acaff070d610f78d1f.png" +loading="lazy" +></p> +<p>(4)解决方案 +在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。</p> +<p>make -j4编译可能遇到的问题:</p> +<ul> +<li><code>sync.c(text.sync_main+0x78):undefined reference to 'syncfs'</code></li> +</ul> +<p><code>分析:</code>可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。</p> +<p><code>解决方法:</code></p> +<p><code>make menuconfig</code> +点击/进入搜索,输入SYNC,根据提示禁用SYNC +最后再make -j4编译一下即可</p> +<p><img src="https://img-blog.csdnimg.cn/7defb1eda80748d29c73a564f2e631be.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2b4ded5286854f1ca4e7d8fae5e148c4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<img src="https://img-blog.csdnimg.cn/932a1580f3b54a5ca685be2b7c5c1dd7.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。</p> +<p>(5)make install简述</p> +<ul> +<li>默认安装位置:./_install</li> +<li>文件包含有:bin linuxrc sbin usr</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/002a97e1448542f784b04d188f6cb7f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->ls -l可以看到: linuxrc -&gt; bin/busybox //这个linuxrc其实就是个符号链接 <!-- raw HTML omitted --></p> +<p><img src="https://img-blog.csdnimg.cn/b97a1a96e2a94503832d05c0f8ca072e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->这里也不难发现,bin下的所有的符号链接都指向了busybox<!-- raw HTML omitted --></p> +<p>(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">make menuconfig +</span></span><span class="line"><span class="cl"> Busybox Settings —&gt; +</span></span><span class="line"><span class="cl"> Installation Options (“make install” behavior) —&gt; +</span></span><span class="line"><span class="cl"> (/root/rootfs/x210_rootfs)BusyBox installation prefix +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行<code>make install</code>后,回到被挂载的目录下,可以发现这四个文件已经生成。</p> +<h2 id="五nfs挂载根文件系统">五、NFS挂载根文件系统 +</h2><h4 id="1nfs简述">1.NFS简述 +</h4><ul> +<li>NFS 是Network File System的缩写,即网络文件系统。</li> +<li>功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。</li> +</ul> +<h4 id="2nfs服务器安装">2.NFS服务器安装 +</h4><p><code>sudo apt-get install nfs-kernel-server</code></p> +<h4 id="3nfs使用过程">3.NFS使用过程 +</h4><p>启动NFS服务器-&gt;启动NFS客户端-&gt;挂载NFS目录</p> +<h4 id="4nfs配置">4.NFS配置 +</h4><ul> +<li>输入命令<code>vim /etc/exports</code></li> +</ul> +<p>在最后一行修改</p> +<ul> +<li><code>&quot;文件挂载目录&quot; *(rw,sync,no_root_squash,no_subtree_check)</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a355d9b6e233404ea19531fa04947910.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>保存退出后,输入<code>mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs</code>(根据实际情况修改)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/9383c4e9c6e74c7485d07a6aec6f99fd.png" +loading="lazy" +></p> +<ul> +<li>输入命令<code>/etc/init.d/nfs-kernel-server restart</code>重启NFS服务</li> +</ul> +<h2 id="六开发板根目录配置">六、开发板根目录配置 +</h2><p>首先将etc目录放置到挂载根目录下</p> +<p>etc目录下载:</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>点击此处</a></p> +<h4 id="1inittab文件详解">1.inittab文件详解 +</h4><p>&lt;1&gt;添加一个典型的inittab文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>inittab下载</a></p> +<p>&lt;2&gt;inittab格式解析</p> +<p><code>id:runlevels:action:process</code></p> +<p><img src="https://img-blog.csdnimg.cn/4f374d2fe1ca4f7da6f22403e314525f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>解释:</p> +<ul> +<li>id:标识符,即代表记录的名字</li> +<li>runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/dd8867359c0c44c6945fc29dbf0a90a3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>action:用于描述该级别该执行什么操作(部分说明)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/99fb967e453c456b989bd57ec0e84020.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>process:具体执行的命令</li> +</ul> +<p>&lt;3&gt;了解busybox init与inittab之间的关系</p> +<ul> +<li>busybox init进程主要完成系统的初始化工作。</li> +</ul> +<p>busybox init进程的工作流程:</p> +<blockquote> +<p><!-- raw HTML omitted -->为init设置信号处理过程-&gt;初始化控制台-&gt;剖析/etc/inittab文件-&gt;执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS-&gt;执行所有导致 init 暂停的 inittab 命令(动作类型: wait)-&gt;执行所有仅执行一次的 inittab(动作类型: once)<!-- raw HTML omitted --></p> +</blockquote> +<ul> +<li>一旦完成以上工作, init 进程便会<code>循环执行</code>以下进程:</li> +</ul> +<blockquote> +<p>&lt;1&gt;执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) +&lt;2&gt;执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)</p> +</blockquote> +<ul> +<li>简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。</li> +</ul> +<p>注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。</p> +<p>&lt;4&gt;配置 +vi命令打开inittab模板文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#first:run the system script file 注释 +</span></span><span class="line"><span class="cl">::sysinit:/etc/init.d/rcS //在控制台初始化之前执行rcS +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::askfirst:-/bin/sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::ctrlaltdel:-/sbin/reboot //执行控制台时的打印信息 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#umount all filesystem //同时按住3键可以重启 +</span></span><span class="line"><span class="cl">::shutdown:/bin/umount -a -r//关机时接触挂载init +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#restart init process//重启时启动 +</span></span><span class="line"><span class="cl">::restart:/sbin/init +</span></span></code></pre></td></tr></table> +</div> +</div><p>修改脚本: +<img src="https://img-blog.csdnimg.cn/0ccb3db4d10c417b9eeb5526f87c7793.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rcs文件详解">2.rcS文件详解 +</h4><p>&lt;1&gt;添加一个典型的rcS文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>rcS下载</a></p> +<p>&lt;2&gt;rcS文件解析</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/sh 需要继续添加环境变量,在后面:/new 即可 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">PATH</span><span class="o">=</span>/sbin:/bin:/usr/sbin:/usr/bin +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">runlevel</span><span class="o">=</span>S +</span></span><span class="line"><span class="cl"><span class="nv">prevlevel</span><span class="o">=</span>N +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">umask</span> <span class="m">022</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> PATH runlevel prevlevel +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -a +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>PATH=xxx</li> +</ul> +<blockquote> +<p>PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。</p> +</blockquote> +<ul> +<li>runlevel=</li> +</ul> +<blockquote> +<p>linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/2c17661c32464ad8a0c96c654e622289.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>umask=</li> +</ul> +<blockquote> +<p>umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。</p> +</blockquote> +<ul> +<li>mount -a</li> +</ul> +<blockquote> +<p>mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)</p> +</blockquote> +<h4 id="3rcs实战">3.rcS实战 +</h4><p>首先将前面提供的etc压缩包模板下载至共享文件夹</p> +<p>&lt;1&gt;输入命令打开rcS脚本:<code>vi etc/init.d/rcS</code>。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了</p> +<p>&lt;2&gt;mdev</p> +<blockquote> +<p>udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。</p> +</blockquote> +<p>rcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在<code>rcS</code>文件中添加以下与mdev有关的2行配置项后:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echo /sbin/mdev &gt; /proc/sys/kernel/hotplug +</span></span><span class="line"><span class="cl">mdev -s +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/d84ea4a6677a4af08741ba6c4b6db580.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>再次启动系统后发现/dev目录下生成了很多的设备驱动文件</p> +<p>&lt;3&gt;hostname</p> +<p><code>我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名</code></p> +<p>hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。</p> +<ul> +<li>添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname</li> +</ul> +<p>&lt;4&gt;ifconfig</p> +<p>(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40</p> +<p><img src="https://img-blog.csdnimg.cn/5842d7cc0dd94c3fbd348189e908f09b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>&lt;5&gt;mount挂载测试</p> +<p>这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="k">var</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">tmp</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="o">......</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,<code>输入mkdir命令在根目录依次创建即可</code>。</p> +<h2 id="七动态链接库的拷贝">七、动态链接库的拷贝 +</h2><h4 id="1静态编译链接测试">1.静态编译链接测试 +</h4><p>首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a.c file-&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">int main() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> printf(&#34;hello world!\n&#34;); +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2解决办法">2.解决办法: +</h4><p><code>拷贝一份动态链接库文件到开发板根目录下</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3解释">3.解释: +</h4><p><img src="https://img-blog.csdnimg.cn/6e39e3914f954ff7967b904a8aa576c5.png" +loading="lazy" +></p> +<p>这时候执行命令./a.out发现可以正常打印</p> +<h4 id="4strip工具">4.strip工具 +</h4><p>动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在<code>传统的嵌入式系统中flash空间是有限的</code>,为了<code>节省空间</code>常常把这些符号信息去掉。这样节省空间并且不影响运行。</p> +<p>去掉符号信息的命令:</p> +<p><code>arm-linux-strip *so*</code></p> +<h2 id="八ext2格式镜像烧录">八、ext2格式镜像烧录 +</h2><h4 id="1确定文件夹格式的rootfs可用">1. 确定文件夹格式的rootfs可用 +</h4><p>前面我们已经提前配置好,此处不再赘述</p> +<p><img src="https://img-blog.csdnimg.cn/560f47331e76495994c412e7f9e97425.png" +loading="lazy" +></p> +<h4 id="2ext2镜像制作">2.ext2镜像制作 +</h4><ul> +<li> +<p>首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。</p> +</li> +<li> +<p>然后输入以下命令:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">losetup /dev/loop1 rootfs.ext2 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mke2fs -m 0 /dev/loop1 10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -t ext2 /dev/loop1 ./ext2_rootfs/ +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时我们复制一份开发板根目录到ext2_rootfs下</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp rootfs.ext2 /mnt/hgfs/Myshare/ -f +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>进入~/rootfs目录,执行清除卸载命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">umount /dev/loop1 +</span></span><span class="line"><span class="cl">losetup -d /dev/loop1 +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时在rootfs目录下可以看见生成了一个rootfs.ext2镜像文件,我们将其复制到共享文件夹下,然后再将其复制到电脑<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>fastboot</a>目录下,执行uboot烧录操作,借鉴该博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a></li> +</ul> +<p>至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!</p> +<hr> +<p>参考资料:</p> +<ul> +<li> +<p><a class="link" href="https://blog.csdn.net/wangweijundeqq/article/details/82533485?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>Linux开发之根文件系统构建及过程详解</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010299133/article/details/93414146" target="_blank" rel="noopener" +>busybox init进程和/etc/inittab关系</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010311609/article/details/123137181?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165080397516782184664736%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165080397516782184664736&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-123137181.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=NFS%E6%8C%82%E8%BD%BDlinux&#43;&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>NFS-LINUX挂载实践</a></p> +</li> +</ul>Ubuntu命令查看手册https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/Mon, 25 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/cover.jpg" alt="Featured image of post Ubuntu命令查看手册" /><h2 id="进程管理类">进程管理类 +</h2><p>1.top命令</p> +<blockquote> +<ul> +<li>top命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。</li> +<li>top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。</li> +</ul> +</blockquote> +<p>2.htop命令</p> +<blockquote> +<ul> +<li>htop命令是top的改进版。</li> +<li>默认情况下,大多数Linux发行版本都没有安装htop。</li> +<li>htop命令显示的信息与top相同,但它的界面更人性化。</li> +</ul> +</blockquote> +<p>3.pstree</p> +<blockquote> +<ul> +<li>pstree命令也可以显示进程信息。</li> +<li>它以树的形式显示进程。</li> +</ul> +</blockquote> +<p>4.kill</p> +<blockquote> +<ul> +<li>kill命令可以根据进程ID来杀死进程。</li> +<li>你可以使用ps -A,top,或者grep命令获取到进程ID。</li> +</ul> +</blockquote> +<pre><code>从技术层面来讲,kill命令可以发送任何信号给一个进程。 +你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。 +</code></pre> +<hr> +<h2 id="文件操作类基础篇">文件操作类(基础篇) +</h2><blockquote> +<p><strong>新建文件:touch</strong><br> +详细文档通过 man [command] 查看</p> +</blockquote> +<blockquote> +<p><strong>管理文件</strong></p> +</blockquote> +<ul> +<li>rm: 删除文件或目录(-r)</li> +<li>mkdir 新建目录</li> +<li>cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r)</li> +<li>mv 移动或重命名文件、目录</li> +</ul> +<blockquote> +<p><strong>压缩tzip文件</strong></p> +</blockquote> +<ul> +<li>zip FileName.zip DirName # 将DirName本身压缩</li> +<li>zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩</li> +</ul> +<blockquote> +<p><strong>解压zip文件</strong></p> +</blockquote> +<ul> +<li>unzip filename</li> +</ul> +<blockquote> +<p><strong>查找含<code>spark</code>的目录、文件</strong></p> +</blockquote> +<ul> +<li>find /home/jack -name &lsquo;<em>spark</em>&rsquo;</li> +</ul> +<blockquote> +<p><strong>更改密码</strong></p> +</blockquote> +<ul> +<li>passwd</li> +</ul> +<blockquote> +<p><strong>更改文件名或移动文件位置</strong></p> +</blockquote> +<ul> +<li>语句:mv oldFileName newFileName</li> +<li>示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt</li> +</ul> +<blockquote> +<p><strong>删除文件</strong></p> +</blockquote> +<ul> +<li>删除文件: rm test.txt</li> +<li>删除空文件夹: rmdir test</li> +<li>删除非空文件夹及其目录下的所有文件夹及文件:rm -r test</li> +<li>删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt)</li> +</ul> +<h2 id="防火墙状态">防火墙状态 +</h2><p>首先需要输入安装命令: +<code>apt install ufw</code></p> +<blockquote> +<p>查看防火墙当前状态 +<code>sudo ufw status</code></p> +</blockquote> +<blockquote> +<p>开启防火墙 +<code>sudo ufw enable</code></p> +</blockquote> +<blockquote> +<p>关闭防火墙 +<code>sudo ufw disable</code></p> +</blockquote> +<blockquote> +<p>查看防火墙版本 +<code>sudo ufw version</code></p> +</blockquote> +<blockquote> +<p>默认允许外部访问本机 +<code>sudo ufw default allow</code></p> +</blockquote> +<blockquote> +<p>默认拒绝外部访问主机 +<code>sudo ufw default deny</code></p> +</blockquote> +<blockquote> +<p>允许外部访问443端口 +<code>sudo ufw allow 443</code></p> +</blockquote> +<blockquote> +<p>拒绝外部访问443端口 +<code>sudo ufw deny 443</code></p> +</blockquote> +<blockquote> +<p>允许某个IP地址访问本机所有端口 +<code>sudo ufw allow from 192.168.0.1</code></p> +</blockquote> +<h2 id="网络设置">网络设置 +</h2><blockquote> +<p>重置网卡 +sudo /etc/init.d/networking restart</p> +</blockquote>CPK-RA6M4智慧门禁系统教学https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/cover.jpg" alt="Featured image of post CPK-RA6M4智慧门禁系统教学" /><p><img src="https://img-blog.csdnimg.cn/img_convert/b98bb037592975e68632b30a8e0845f6.png" +loading="lazy" +alt="image-20220804171524901" +></p> +<h2 id="1项目介绍">1、项目介绍 +</h2><p>本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。</p> +<p>下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。</p> +<h2 id="2前期准备">2、前期准备 +</h2><p>开发工具:</p> +<ul> +<li>RT-Thread Studio</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a95d6ef5c3224144b554bcb416691bcf.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。</p> +<p>RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。</p> +<p>下载链接:<a class="link" href="https://www.rt-thread.org/page/download.html#studio" target="_blank" rel="noopener" +>RT-Thread Studio 下载</a></p> +<ul> +<li>瑞萨FSP(灵活配置软件包)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fbdf24dd4b66b39b2f108f558ecf4617.png" +loading="lazy" +alt="Flexible Software Package (FSP)" +></p> +<p>瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。</p> +<p>下载链接:<a class="link" href="https://github.com/renesas/fsp/releases/tag/v3.5.0" target="_blank" rel="noopener" +>瑞萨FSP v3.5.0</a></p> +<p>模块:</p> +<ul> +<li>AHT10</li> +<li>ESP8266</li> +<li>RC522及读卡标签</li> +<li>ssd1306 OLED显示屏</li> +</ul> +<h2 id="3模块介绍及使用">3、模块介绍及使用 +</h2><h4 id="31-aht10">3.1 AHT10 +</h4><h6 id="311底层i2c通信协议简介">3.1.1底层I2C通信协议简介 +</h6><p>I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。</p> +<p>而I2C通信的读写数据是通过等待从机的应答信号(ACK)。</p> +<p>也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。</p> +<p>这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。</p> +<p>当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。</p> +<p>简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。</p> +<h6 id="312-sensor框架的使用">3.1.2 sensor框架的使用 +</h6><p>在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。</p> +<p>掌握sensor框架的使用,需要了解一下API的调用:</p> +<table> +<thead> +<tr> +<th style="text-align:center"><strong>函数</strong></th> +<th style="text-align:center"><strong>描述</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">rt_device_find()</td> +<td style="text-align:center">根据传感器设备设备名称查找设备获取设备句柄</td> +</tr> +<tr> +<td style="text-align:center">rt_device_open()</td> +<td style="text-align:center">打开传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_read()</td> +<td style="text-align:center">读取数据</td> +</tr> +<tr> +<td style="text-align:center">rt_device_control()</td> +<td style="text-align:center">控制传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_set_rx_indicate()</td> +<td style="text-align:center">设置接收回调函数</td> +</tr> +<tr> +<td style="text-align:center">rt_device_close()</td> +<td style="text-align:center">关闭传感器设备</td> +</tr> +</tbody> +</table> +<h6 id="313-aht10对接到sensor框架">3.1.3 AHT10对接到sensor框架 +</h6><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">SCL</td> +<td style="text-align:center">P512</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P511</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动-&gt;Enable I2C BUS-&gt;使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f301db2fd8e1988f2ca4e311c5d973cf.png" +loading="lazy" +alt="image-20220805110607476" +></p> +<p>然后使用下面的程序完成模块初始化工作</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;sensor_asair_aht10.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define AHT10_I2C_BUS &#34;i2c1&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 模块初始化工作 */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_aht10_port</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_sensor_config</span> <span class="n">cfg</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">dev_name</span> <span class="o">=</span> <span class="n">AHT10_I2C_BUS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">user_data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">AHT10_I2C_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_init</span><span class="p">(</span><span class="s">&#34;aht10&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_ENV_EXPORT</span><span class="p">(</span><span class="n">rt_hw_aht10_port</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>AHT10温湿度数据读取</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="c1">// AHT10设备读取数值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">aht10_device_t</span> <span class="n">dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_port</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">dev</span> <span class="o">=</span> <span class="nf">aht10_init</span><span class="p">(</span><span class="n">AHT10_I2C_BUS</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes failure&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes ok!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read humidity 采集湿度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="nf">aht10_read_humidity</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read temperature 采集温度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="nf">aht10_read_temperature</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="32-esp8266">3.2 ESP8266 +</h4><h6 id="321-底层uart简介">3.2.1 底层uart简介 +</h6><p>UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。</p> +<p>UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。</p> +<ul> +<li>串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。</li> +<li>异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。</li> +<li>数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5fdffba894c94d48a14c4f64a9992b93.jpeg" +loading="lazy" +alt="查看源图像" +></p> +<p>空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。</p> +<p>起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。</p> +<p>数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。<code>先发送最低位,最后发送最高位</code>,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。</p> +<h6 id="322-mqtt通讯协议介绍">3.2.2 MQTT通讯协议介绍 +</h6><p>MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quot;轻量级&quot;通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。</p> +<p>其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。</p> +<p>实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。</p> +<p><img src="https://img-blog.csdnimg.cn/a665ee8ebb4d427bbfa4c8a7ec013913.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h6 id="323-at组件">3.2.3 AT组件 +</h6><p>AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/1eb3c2cd78584efa85656a2cdd8daa8f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。</p> +<h6 id="324-mqtt协议及at组件在rt-thread中的使用">3.2.4 MQTT协议及AT组件在RT-Thread中的使用 +</h6><p><strong>RT-Thread Settings设置</strong></p> +<p>添加AT Device及OneNET软件包</p> +<p>AT Device配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf1c743b728c70c2764a3db1d368039c.png" +loading="lazy" +alt="image-20220805122341394" +></p> +<p>OneNET配置:</p> +<p>首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b40025d68d9bd0f32ff6efa3b74ff12d.png" +loading="lazy" +alt="image-20220805122741348" +> +<img src="https://img-blog.csdnimg.cn/img_convert/c7c17c8d743dca043a098be627baf93c.png" +loading="lazy" +alt="image-20220805122836636" +></p> +<p>然后将创建的信息填写到settings中</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9588bef3c3bf99d27bdc3cbd56394ece.png" +loading="lazy" +alt="image-20220805123248475" +></p> +<p>在组件中使能AT命令</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ad6b80e0d34df83a213dcdbf85d4416b.png" +loading="lazy" +alt="image-20220805123407687" +></p> +<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">TX</td> +<td style="text-align:center">P100</td> +</tr> +<tr> +<td style="text-align:center">RX</td> +<td style="text-align:center">P101</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">5V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p><strong>FSP配置</strong></p> +<p>由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置</p> +<p>首先点击<code>RA Smart Configurator</code>,记住这里使用的FSP版本为<code>v3.5.0</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/7710c9a62ad3a4486362f9d4bf92869f.png" +loading="lazy" +alt="image-20220805152204348" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2cb89487678dcf16bf3c784851a42091.png" +loading="lazy" +alt="image-20220805153017364" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf0866f3d50eae91f43aee142ef06966.png" +loading="lazy" +alt="image-20220805153317144" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/58fb0f18f54f0eaf49598c6c20f67b62.png" +loading="lazy" +alt="image-20220805153416015" +></p> +<p>完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现<code>#include &lt;dfs_posix.h&gt;</code>未参与编译以及还有其他一些问题,可以参考这一issue<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6188" target="_blank" rel="noopener" +>[CPK-RA6M4] onenet上云报错&lt;RT-Thread 的版本为 4.1.0 及以上&gt;</a></p> +<p>现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。</p> +<p>然后就是数据上云,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;temperature&#34;</span><span class="p">,</span><span class="n">temperature</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_delay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;humidity&#34;</span><span class="p">,</span><span class="n">humidity</span> <span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/096cd5faec78062ac227adcc12f08f05.png" +loading="lazy" +alt="image-20220805145942277" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67bd30c613f9a819cc2b7abddb58a5bc.png" +loading="lazy" +alt="image-20220805145958887" +></p> +<h4 id="33-rc522">3.3 RC522 +</h4><h6 id="331-底层spi协议简介">3.3.1 底层SPI协议简介 +</h6><p>SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9d4277d0aba7be84c59b68efb9402995.png" +loading="lazy" +alt="SPI 主设备和从设备的连接方式" +></p> +<ul> +<li>MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。</li> +<li>MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。</li> +<li>SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。</li> +<li>CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。</li> +</ul> +<p>整体的传输大概可以分为以下几个过程:</p> +<p>(1)主机先将<code>NSS</code>信号拉低,这样保证开始接收数据;</p> +<p>(2)当<strong>接收端</strong>检测到时钟的边沿信号时,它将立即读取<strong>数据线</strong>上的信号,这样就得到了一位数据(1<code>bit</code>;由于时钟是随数据一起发送的,因此指定<strong>数据的传输速度并不重要</strong>,尽管设备将具有可以运行的最高速度。</p> +<p>(3)<strong>主机</strong>发送到<strong>从机</strong>时:主机产生相应的时钟信号,然后数据<strong>一位一位</strong>地将从<code>MOSI</code>信号线上进行发送到从机;</p> +<p>(4)<strong>主机</strong>接收<strong>从机</strong>数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过<code>MISO</code>信号线发送;</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/3c32f25bed1d6e44c840608e4e352fc4.png" +loading="lazy" +alt="查看源图像" +></p> +<h6 id="332-rc522读卡机制说明">3.3.2 RC522读卡机制说明 +</h6><p>首先来看下RC522与M1卡的通讯流程:</p> +<p><strong>寻卡-&gt;防止卡片冲撞-&gt;选卡-&gt;休眠-&gt;发送0x40(7bit)-&gt;发送0x43-&gt;发送0xa0等4字节-&gt;发送0x00等18字节</strong></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/4c59b975aa9fdccbb19b38b059b87e1a.png" +loading="lazy" +alt="image-20220805154320392" +></p> +<ul> +<li> +<p>复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。</p> +</li> +<li> +<p>防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。</p> +</li> +<li> +<p>选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。</p> +</li> +<li> +<p>三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。</p> +</li> +<li> +<p>对数据块的操作: +读(Read):读一个块的数据; +写(Write):在一个块中写数据; +加(Increment):对数据块中的数值进行加值; +减(Decrement):对数据块中的数值进行减值; +传输(Transfer):将数据寄存器中的内容写入数据块中; +中止(Halt):暂停卡片的工作;</p> +</li> +</ul> +<h6 id="333-rc522在rt-thread的使用">3.3.3 RC522在RT-Thread的使用 +</h6><p>首先打开settings,添加RC522软件包,并在硬件部分使能SPI1</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ef7c08d20f957c70b67fe63943fec730.png" +loading="lazy" +alt="image-20220805155052783" +></p> +<p>打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/263c237d561d232466249aacb0dd42a4.png" +loading="lazy" +alt="image-20220805155448374" +></p> +<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">MOSI</td> +<td style="text-align:center">P411</td> +</tr> +<tr> +<td style="text-align:center">MISO</td> +<td style="text-align:center">P410</td> +</tr> +<tr> +<td style="text-align:center">SCL</td> +<td style="text-align:center">P412</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P311</td> +</tr> +<tr> +<td style="text-align:center">RST</td> +<td style="text-align:center">P312</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +<tr> +<td style="text-align:center">IRQ</td> +<td style="text-align:center">悬空</td> +</tr> +</tbody> +</table> +<p>代码部分参考RC522sample</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/474416ef76e9523302b9cdd544bbf03b.png" +loading="lazy" +alt="image-20220805155715593" +></p> +<p>SPI初始化配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;mfrc522.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_spi_device</span> <span class="n">mfrc522_spi_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">pin</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> <span class="n">spi_cs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_spi_rc522_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_err_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Attach Device +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span> <span class="o">=</span> <span class="n">MFRC522_SS_PIN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span> <span class="o">=</span> <span class="nf">rt_spi_bus_attach_device</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">,</span> <span class="n">MFRC522_SPI_BUS_NAME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">spi_cs</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[RC522] Failed to attach device %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Set device SPI Mode +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="n">rt_spi_configuration</span> <span class="n">cfg</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">data_width</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">RT_SPI_MASTER</span> <span class="o">|</span> <span class="n">RT_SPI_MODE_0</span> <span class="o">|</span> <span class="n">RT_SPI_MSB</span> <span class="o">|</span> <span class="n">RT_SPI_NO_CS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">max_hz</span> <span class="o">=</span> <span class="n">MFRC522_SPICLOCK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_spi_configure</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 导出到自动初始化 */</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_hw_spi_rc522_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>另外需要在完成一下配置,<code>双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5045a3933b508b5267b5fb9eeec6064b.png" +loading="lazy" +alt="image-20220805155922942" +></p> +<p>打开mfrc522.c,修改配置<code>MFRC522_SS_PIN</code>及<code>MFRC522_RST_PIN</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c61dba211ccb8ece988de9e703dc15cb.png" +loading="lazy" +alt="image-20220805161330936" +></p> +<p>打开rtconfig.h,找到以下两个引脚的定义,修改成如下:</p> +<p>注意:<strong><code>一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置</code></strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define MFRC522_SS_PIN 0x3b +</span></span><span class="line"><span class="cl">#define MFRC522_RST_PIN 0x3c +</span></span></code></pre></td></tr></table> +</div> +</div><p>至此,RC522的相关配置结束</p> +<h4 id="34-ssd1306">3.4 SSD1306 +</h4><h6 id="341-底层i2c通信协议">3.4.1 底层I2C通信协议 +</h6><p>(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)</p> +<h6 id="342-ssd1306在rt-thred的使用">3.4.2 SSD1306在RT-Thred的使用 +</h6><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">SCL</td> +<td style="text-align:center">P400</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P401</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>RT-Thread Settings配置:</p> +<p>添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c6b56810a69b472ea12eaa4e8d60008a.png" +loading="lazy" +alt="image-20220805162320450" +></p> +<p>打开rtconfig.h,添加i2c代码,<code>注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SCL_PIN 0x400 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SDA_PIN 0x401 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开drv_soft_i2c.c文件,添加代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define I2C0_BUS_CONFIG \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> { \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .scl = BSP_I2C0_SCL_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .sda = BSP_I2C0_SDA_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .bus_name = &#34;i2c0&#34;, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> } +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/04a3d96e15bbde106c73e389eca7fe10.png" +loading="lazy" +alt="image-20220805162941069" +></p> +<p>生成配置之后添加用户代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;ssd1306.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">25</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Hello RT-Thread!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_APP_EXPORT</span><span class="p">(</span><span class="n">oled_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实时时钟显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Now Time&#34;</span><span class="p">,</span> <span class="n">Font_16x26</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">40</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;:&#34;</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>温湿度数据显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Humi_Temp_Detection!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Temperature: %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Temperature_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Humidity:%d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">47</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Humidity_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4整体代码框架">4、整体代码框架 +</h2><h4 id="41-多线程任务分配">4.1 多线程任务分配 +</h4><p>本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。</p> +<p>所以共创建四个线程:</p> +<p>(1)RC522_thread:用于RC522读卡</p> +<p>(2)aht10_read_thread:用于aht10读取温湿度数值</p> +<p>(3)onenet_aht10_thread:云端数据上报</p> +<p>(4)oled_thread:OLED显示</p> +<h4 id="42-线程间交互">4.2 线程间交互 +</h4><p>本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。</p> +<h4 id="43-代码整合">4.3 代码整合 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/8aed1d64ef9fd8e219744b794b8dd048.png" +loading="lazy" +alt="image-20220802210559475" +></p> +<p>在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。</p> +<p>都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/36369721fa7745022aab2ad2492dc64f.png" +loading="lazy" +alt="image-20220805171602257" +></p> +<h2 id="5踩坑指南">5、踩坑指南 +</h2><p>其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:</p> +<p>(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为<code>v3.5.0</code></p> +<p>(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。</p> +<p>(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。</p> +<div class="video-wrapper"> +<iframe src="https://player.bilibili.com/player.html?as_wide=1&amp;high_quality=1&amp;page=1.8&bvid=BV1Ld4y1N7eo" +scrolling="no" +frameborder="no" +framespacing="0" +allowfullscreen="true" +> +</iframe> +</div>Study210利用SD运行流水灯程序https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post Study210利用SD运行流水灯程序" /><h2 id="1安装ecilpse">1.安装ecilpse +</h2><h4 id="1确认自己的pc机开发环境开发板光盘中有如下四个eclipse包">(1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包: +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_32.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_32.7z +</span></span></code></pre></td></tr></table> +</div> +</div><p>选择自己需求对应的安装包下载解压即可(<a class="link" href="https://download.csdn.net/download/qq_56914146/85162554" target="_blank" rel="noopener" +>此处可点击下载</a>)</p> +<h4 id="2配置好eclipse的环境变量">(2)配置好eclipse的环境变量 +</h4><p>借鉴<a class="link" href="https://blog.csdn.net/m0_46165586/article/details/107296429?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165018384616781685349830%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165018384616781685349830&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107296429.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=eclipse%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>Eclipse环境变量配置-超详细</a></p> +<h2 id="2开始工程的创建">2.开始工程的创建 +</h2><h4 id="1首先双击eclipseexe文件进入初次进入需要选择一个存储位置作为工程存放处workplace">(1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace) +</h4><h4 id="2建一个流水灯工程">(2)建一个流水灯工程 +</h4><p>首先在Project Explorer的空白栏右键单击-&gt;New-&gt;C Project +<img src="https://img-blog.csdnimg.cn/0b37eba37269446faf5de58793963da2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +项目名称填写LED_test +<img src="https://img-blog.csdnimg.cn/0b7cce5b3fa341f98792a316a1937054.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +点击next,finish</p> +<p>找到我们的项目工程示例,将全部文件复制到剪贴板 +<img src="https://img-blog.csdnimg.cn/2bbe14f0a69a46fe8328ce92f1492421.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键选择paste,选择粘贴全部 +<img src="https://img-blog.csdnimg.cn/842db416ea2c4929ac655d29bc4bfb07.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +这是粘贴好的文件项目 +<img src="https://img-blog.csdnimg.cn/d1dae4dddaf346b1be377c674fefdd35.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键Build Project或直接CTRL+B编译 +<img src="https://img-blog.csdnimg.cn/9389ca0a332143fdbfb650e41fb84f2b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 +<img src="https://img-blog.csdnimg.cn/776361da8d1045c3a39af79804bf0320.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +进入该目录下,可以发现生成了led.bin映像文件 +<img src="https://img-blog.csdnimg.cn/e497619b0ab74765aaffd33dc55be299.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="3下载源码到sd卡">3.下载源码到SD卡 +</h2><p>打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 +<img src="https://img-blog.csdnimg.cn/07008c13a27e41bebc960a47747c2283.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="4实例演示">4.实例演示 +</h2><h4 id="1清除开发板中的bootloader">(1)清除开发板中的bootloader +</h4><p>由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a>)</p> +<h4 id="2通过sd卡运行裸机程序">(2)通过SD卡运行裸机程序 +</h4><p>将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 +<img src="https://img-blog.csdnimg.cn/ddcba636b89841629cc4eba87b6a90b2.gif" +loading="lazy" +alt="在这里插入图片描述" +></p>Study210开发板刷安卓系统https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/Sat, 23 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/cover.jpg" alt="Featured image of post Study210开发板刷安卓系统" /><h2 id="一破坏bootloader">一、破坏BootLoader +</h2><blockquote> +<p>1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/c79baf4eb1e949c88d6bb50c32862354.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)</p> +</blockquote> +<blockquote> +<p>3.输入root(password:123456)</p> +</blockquote> +<blockquote> +<p>4.然后输入<code>busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync</code></p> +</blockquote> +<blockquote> +<p>5.回车后显示</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">1+0 records in +</span></span><span class="line"><span class="cl">1+O records out +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 +此时重新启动开发板就无法启动了</p> +</blockquote> +<h2 id="二sd卡刷机烧录uboot到sd卡中">二、SD卡刷机(烧录uboot到SD卡中) +</h2><blockquote> +<p>1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/958a8cf2a0554edd8e2d53d021490d4e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->此处如果SD烧写不成功,可尝试用管理员身份运行。 +<code>插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.</code></p> +<blockquote> +<p>2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)</p> +</blockquote> +<h2 id="三fastboot-下载安装镜像">三、fastboot 下载安装镜像 +</h2><blockquote> +<p>1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。</p> +</blockquote> +<blockquote> +<p>2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/bc1cb6ad4904482baaad59e05da074bc.png" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wex7LBk8-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415202849623.png)\]" +></p> +<blockquote> +<p>3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android</p> +</blockquote> +<blockquote> +<p><code>fastboot目录下应该包含的文件</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/850cde9ff40e4109a2b46cd186f93418.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p><code> Android中应该包含的文件(由于这里我烧写的是安卓系统)</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d97c6282c3ba46aba3a44b34a72e99a4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3DezB8H-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203108592.png)\]" +></p> +<blockquote> +<p>4.进行内核和系统的烧写 ,具体代码如下:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/eb401fcf50ec4f228025341cfcb28fca.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Dhso3IG-1650028395334)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203639928.png)\]" +></p> +<blockquote> +<p>同时在SecureCRT下可以看到下载结果</p> +</blockquote> +<blockquote> +<p>5.最后在windows控制台下输入<code> fastboot reboot</code>命令重启系统即可。</p> +</blockquote> +<h2 id="四dnw-刷机用fastboot刷android-">四、dnw 刷机(用fastboot刷Android ) +</h2><ul> +<li>准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/763acfc49ae34659b891a95ccd3de444.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaxHZTvW-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415204109660.png)\]" +></p> +<p>注意:</p> +<p>(1)安装<code>SecBulk.sys Njsmodi 2416 dnw drive</code>的驱动程序在<code>\X210V3S_A\tools\USB驱动\dnw_driver</code>下,安装驱动需要禁用数字签名(可参考<a class="link" href="https://blog.csdn.net/m0_37182543/article/details/80541418?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165002148616780271549615%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=165002148616780271549615&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-80541418.142%5ev9%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=Windows%E7%A6%81%E7%94%A8%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>win10如何永久关闭数字签名</a>)</p> +<p>(2)在使用dnw过程中需要长按电源键,否则会断开连接。</p> +<p>刷机步骤:</p> +<blockquote> +<p>1.将拨码开关拨到USB启动位置。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/51ddaa8b66494111899de8774b695007.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rua1zZN3-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415205448252.png)\]" +></p> +<blockquote> +<p>2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/63fbc995f8ab4752945842db148ad6a5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/170c0ec22ea4421daa7952994fdd3b0d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/e08d1f32d26d4558b078f85db271eab4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>3.(<code>同上操作</code>)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin</p> +</blockquote> +<blockquote> +<p><code> 注意!!!</code>:下载的同时要看<code>SecureCRT界面</code>,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。</p> +</blockquote> +<blockquote> +<p>4.回到secureCRT</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入fdisk -c 0 (进行分区) +</span></span><span class="line"><span class="cl">输入fastboot (查看分区) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/7676539a597a42d38993936ee760236a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<code>最后再输入</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fastboot -w +</span></span></code></pre></td></tr></table> +</div> +</div><p>全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。</p> +<p><img src="https://img-blog.csdnimg.cn/2982435176bb485abd152c2ab508d2cc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p>此文章参考于<a class="link" href="https://blog.csdn.net/madao1234/article/details/101104872" target="_blank" rel="noopener" +>S5PV210 Study210开发板刷系统</a></p>ART-Pi 网络时钟https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/cover.jpg" alt="Featured image of post ART-Pi 网络时钟" /><h2 id="玩转rt-thread自制网络时钟">《玩转RT-Thread》自制网络时钟 +</h2><hr> +<p>@[toc]</p> +<h2 id="一准备工作">一、准备工作 +</h2><ul> +<li> +<p>开发平台:RT-Thread Studio</p> +</li> +<li> +<p>开发板:ART-PI</p> +</li> +<li> +<p>主控芯片:STM32H750</p> +</li> +<li> +<p>温湿度传感器:SHT30</p> +</li> +<li> +<p>显示模组:0.96’OLED(SSD1306)</p> +</li> +<li> +<p>串口调试助手:SecureCRT</p> +</li> +</ul> +<p>注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。</p> +<h2 id="二新建rt-thread-项目">二、新建RT-Thread 项目 +</h2><p><img src="https://img-blog.csdnimg.cn/dfeff108ee0241919514065992e79ef8.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/9f49c13343914adf8d92f12a1ebf832e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="三获取温湿度数据">三、获取温湿度数据 +</h2><h4 id="1双击打开左边导航栏的rt-thread-setting">1、双击打开左边导航栏的RT-Thread Setting +</h4><p><img src="https://img-blog.csdnimg.cn/096e053c2ec545a9950c86dcb1e12d9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2使能软件模拟i2c单击点亮即可">2、使能软件模拟i2c(单击点亮即可) +</h4><p><img src="https://img-blog.csdnimg.cn/6bb6a362155641c0b0b6fa0953c60e45.png" +loading="lazy" +></p> +<h4 id="3配置i2c及相关引脚">3、配置i2c及相关引脚 +</h4><p><code>这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置</code></p> +<p><img src="https://img-blog.csdnimg.cn/ae8aaaa39cf04296809e01ccef73d980.png" +loading="lazy" +></p> +<h4 id="4添加sht3x软件包">4、添加SHT3X软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/d480f380b622466c9c38ae5129550067.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置,点击编译并下载</code></p> +<p>具体RT-Thread Studio的一般使用可参照<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124079730?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)</a></p> +<p><code>此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功</code></p> +<p><img src="https://img-blog.csdnimg.cn/04803141590e474bbe767242a8258ed5.png" +loading="lazy" +></p> +<p>此时在串口输入help,可以看出有一个sht3x配置</p> +<p><img src="https://img-blog.csdnimg.cn/bb9d35af5d19463282a1bd8400e90364.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入: +</span></span><span class="line"><span class="cl">sht3x probe i2c3 pd +</span></span><span class="line"><span class="cl">sht3x read(读取温湿度信息) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="四获取ntp时间">四、获取NTP时间 +</h2><h4 id="1使能选择wifi框架">1、使能选择WiFi框架 +</h4><p><img src="https://img-blog.csdnimg.cn/fac0022dff324acc9aa4a94e85407e69.png" +loading="lazy" +></p> +<h4 id="2使能ap6212库">2、使能AP6212库 +</h4><p><img src="https://img-blog.csdnimg.cn/97afeb11678140b2a5acbea44bc8937f.png" +loading="lazy" +></p> +<h4 id="3添加easyflash和netutils软件包">3、添加easyflash和netutils软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/08cda56d446541358d2b5038545ca284.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>鼠标右键netutils打开配置项</code></p> +<p><img src="https://img-blog.csdnimg.cn/cd98d8f9bb0f4f15941c4617c32b7aa3.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>使能NTP (网络时间协议)客户端 </code></p> +<p><img src="https://img-blog.csdnimg.cn/7fe0c1a627d94d1dba87dbcf4918d127.png" +loading="lazy" +></p> +<p><code>使能软件模拟RTC</code></p> +<p><img src="https://img-blog.csdnimg.cn/f2ac26826c0a463bb1124804fcc7c563.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置</code></p> +<p><code>修改配置</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cassandra" data-lang="cassandra"><span class="line"><span class="cl"><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="err">打开电脑中项目所在的路径</span><span class="o">-</span><span class="n">workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">packages</span><span class="o">-</span><span class="n">EasyFlash</span><span class="o">-</span><span class="n">v4</span><span class="err">.1.0</span><span class="o">-</span><span class="n">port</span><span class="err">,将</span><span class="n">port目录下的ef_fal_port</span><span class="p">.</span><span class="n">c文件复制到workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">board</span><span class="o">-</span><span class="n">port中</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="err">修改</span><span class="n">port中宏定义FAL_EF_PART_NAME</span><span class="w"> </span><span class="err">中的名字</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">#</span><span class="n">define</span><span class="w"> </span><span class="n">FAL_EF_PART_NAME</span><span class="w"> </span><span class="s">&#34;easyflash&#34;</span><span class="w"> </span><span class="c1">//修改后的宏定义 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>此时再编译并下载到开发板中</code></p> +<h4 id="4连接wifi">4、连接WiFi +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">wifi</span> <span class="n">scan</span> <span class="c1">//搜索wifi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">wifi</span> <span class="n">join</span> <span class="p">[</span><span class="n">SSID</span><span class="p">]</span> <span class="p">[</span><span class="n">PASSWORD</span><span class="p">]</span> <span class="c1">//连接WiFi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="nl">SSID</span><span class="p">:</span><span class="n">WiFi名称</span> +</span></span><span class="line"><span class="cl"><span class="n">PASSWORD</span><span class="err">:</span><span class="n">WiFi密码</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5设置开机自连接wifi">5、设置开机自连接WiFi +</h4><p><code>(1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_WIFI +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_mgnt.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_cfg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_prot.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;easyflash.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;fal.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#if (EF_SW_VERSION_NUM &lt; 0x40000) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">base64_table</span><span class="p">[</span><span class="mi">65</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="mi">256</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3E</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3F</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x34</span><span class="p">,</span> <span class="mh">0x35</span><span class="p">,</span> <span class="mh">0x36</span><span class="p">,</span> <span class="mh">0x37</span><span class="p">,</span> <span class="mh">0x38</span><span class="p">,</span> <span class="mh">0x39</span><span class="p">,</span> <span class="mh">0x3A</span><span class="p">,</span> <span class="mh">0x3B</span><span class="p">,</span> <span class="mh">0x3C</span><span class="p">,</span> <span class="mh">0x3D</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0A</span><span class="p">,</span> <span class="mh">0x0B</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x0D</span><span class="p">,</span> <span class="mh">0x0E</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x10</span><span class="p">,</span> <span class="mh">0x11</span><span class="p">,</span> <span class="mh">0x12</span><span class="p">,</span> <span class="mh">0x13</span><span class="p">,</span> <span class="mh">0x14</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x16</span><span class="p">,</span> <span class="mh">0x17</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="mh">0x19</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0x1B</span><span class="p">,</span> <span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x1D</span><span class="p">,</span> <span class="mh">0x1E</span><span class="p">,</span> <span class="mh">0x1F</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="mh">0x21</span><span class="p">,</span> <span class="mh">0x22</span><span class="p">,</span> <span class="mh">0x23</span><span class="p">,</span> <span class="mh">0x24</span><span class="p">,</span> <span class="mh">0x25</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0x27</span><span class="p">,</span> <span class="mh">0x28</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x29</span><span class="p">,</span> <span class="mh">0x2A</span><span class="p">,</span> <span class="mh">0x2B</span><span class="p">,</span> <span class="mh">0x2C</span><span class="p">,</span> <span class="mh">0x2D</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x2F</span><span class="p">,</span> <span class="mh">0x30</span><span class="p">,</span> <span class="mh">0x31</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0x33</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pos</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">end</span><span class="p">,</span> <span class="o">*</span><span class="n">in</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">olen</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">=</span> <span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="cm">/* 3-byte blocks to 4-byte */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">+=</span> <span class="n">olen</span> <span class="o">/</span> <span class="mi">72</span><span class="p">;</span> <span class="cm">/* line feeds */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span><span class="o">++</span><span class="p">;</span> <span class="cm">/* nul termination */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">end</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span> <span class="o">+</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pos</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">6</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x3f</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * return: length, 0 is error. +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">input_length</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">out_len</span> <span class="o">=</span> <span class="n">input_length</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">input_length</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_a</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_b</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_c</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_d</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">triple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sextet_a</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_b</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_c</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_d</span> <span class="o">&lt;&lt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">6</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_info</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">,</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">),</span> <span class="n">buff</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_len</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">wlan_cfg_len</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">base64_buf</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">base64_buf</span> <span class="o">=</span> <span class="nf">rt_malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span> <span class="cm">/* 3-byte blocks to 4-byte, and the end. */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">base64_buf</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* (EF_SW_VERSION_NUM &lt; 0x40000) */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">rt_wlan_cfg_ops</span> <span class="n">ops</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_cfg</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">get_len</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_cfg</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">easyflash_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_set_ops</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ops</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_cache_refresh</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在main.c中添加自动连接函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define LED_PIN GET_PIN(I, 8) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* init Wi-Fi auto connect feature */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* enable auto reconnect on WLAN device */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。</code></p> +<h2 id="五oled屏显示温湿度和实时时间信息">五、OLED屏显示温湿度和实时时间信息 +</h2><h4 id="1添加u8g2软件包">1、添加u8g2软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/9aa5ecc3b3484b14b1c57ef4c75aae73.png" +loading="lazy" +></p> +<h4 id="2编写oled_display显示线程">2、编写oled_display显示线程 +</h4><p><code>(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。</code></p> +<p><code>代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rthw.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;U8g2lib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;drv_soft_i2c.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sht3x.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">sht3x_device_t</span> <span class="nf">sht3x_init</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">i2c_bus_name</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">sht3x_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="nf">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device_t</span> <span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define OLED_I2C_PIN_SCL 24 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define OLED_I2C_PIN_SDA 25 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">U8G2_SSD1306_128X64_NONAME_F_SW_I2C</span> <span class="nf">u8g2</span><span class="p">(</span><span class="n">U8G2_R0</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* clock=*/</span> <span class="n">OLED_I2C_PIN_SCL</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* data=*/</span> <span class="n">OLED_I2C_PIN_SDA</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* reset=*/</span> <span class="n">U8X8_PIN_NONE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define SUN 0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SUN_CLOUD 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define CLOUD 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RAIN 3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define THUNDER 4 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeatherSymbol</span><span class="p">(</span><span class="n">u8g2_uint_t</span> <span class="n">x</span><span class="p">,</span> <span class="n">u8g2_uint_t</span> <span class="n">y</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// fonts used: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_embedded_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_weather_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">69</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN_CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">65</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">64</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">RAIN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">THUNDER</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_embedded_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeather</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">degree</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">degree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawHumidity</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">humidity</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;%&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">48</span><span class="o">+</span><span class="mi">3</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;Hi~&#34;</span><span class="p">);</span> <span class="c1">// requires enableUTF8Print() +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_6x13_tr</span><span class="p">);</span> <span class="c1">// choose a suitable font +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s">&#34;By Mculover666&#34;</span><span class="p">);</span> <span class="c1">// write something to the internal memory +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device_t</span> <span class="n">sht3x_device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device</span> <span class="o">=</span> <span class="n">sht3x_init</span><span class="p">(</span><span class="s">&#34;i2c3&#34;</span><span class="p">,</span> <span class="mh">0x44</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">mstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">hstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">time_t</span> <span class="n">now</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="nc">tm</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">min</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">hour</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">0</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">(</span><span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">=</span><span class="n">gmtime</span><span class="p">((</span><span class="k">const</span> <span class="n">time_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">now</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">hour</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_hour</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">min</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_min</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">min</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">hour</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">firstPage</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">do</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso42_tn</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">hstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="s">&#34;:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">67</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">mstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span> <span class="n">u8g2</span><span class="p">.</span><span class="n">nextPage</span><span class="p">()</span> <span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">1</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeather</span><span class="p">(</span><span class="n">SUN</span><span class="p">,</span> <span class="n">temperature</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">2</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">humidity</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawHumidity</span><span class="p">(</span><span class="n">RAIN</span><span class="p">,</span> <span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">oled_display</span><span class="p">,</span> <span class="n">oled</span> <span class="n">start</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在 applications 文件夹下创建oled_display.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* APPLICATIONS_OLED_DISPLAY_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(3)最终的主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2020, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2020-09-02 RT-Thread first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">oled_display</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/*-------------------------- I2C CONFIG BEGIN --------------------------*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C1_SCL_PIN 24 </span><span class="c1">// p2 10 PB8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C1_SDA_PIN 25 </span><span class="c1">// p2 7 PB9 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C3_SCL_PIN 119 </span><span class="c1">//p1 29 PH7 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C3_SDA_PIN 120 </span><span class="c1">//p1 28 PH8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/*-------------------------- UART CONFIG END --------------------------*/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六实验展示">六、实验展示 +</h2><p><img src="https://img-blog.csdnimg.cn/c0cbf5357ce14d7d963684d4338eee9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/d329c18ee11d45a59252f42bb043663b.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/99f00b0cf72b4e20a0697914e7048f97.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="七问题总结">七、问题总结 +</h2><p><code>注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// cpp函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。</code></p> +<hr> +<p>这次的分享就到这里,有相关问题的欢迎留言私信!</p>ifconfig不显示ip地址https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/cover.jpg" alt="Featured image of post ifconfig不显示ip地址" /><h4 id="ubuntu终端下命令ifconfig的问题解决">ubuntu终端下命令ifconfig的问题解决 +</h4><blockquote> +<p>问题一. ifconfig之后只显示lo,没有看到eth0 +问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 +问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<h4 id="问题一ifconfig之后只显示lo没有看到eth0-">问题一:ifconfig之后只显示lo,没有看到eth0 ? +</h4><blockquote> +<p>1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 +ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback +这边的设置是本地回路。在后面加上</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">iface eth0 inet static +</span></span><span class="line"><span class="cl">address 192.168.1.230 //(ip地址) +</span></span><span class="line"><span class="cl">netmask 255.255.255.0 //(子网掩码) +</span></span><span class="line"><span class="cl">gateway 192.168.1.1 //(网关) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。</p> +</blockquote> +<blockquote> +<p>2.eth0被关了 +输入命令行:ifconfig eth0 up #开启eth0</p> +</blockquote> +<hr> +<h4 id="问题二ifconfig之后显示eth0但是没有显示inet地址广播掩码-">问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”? +</h4><blockquote> +<p>1.先用sudo dhclient eth0更新IP地址 +2.然后运行sudo ifconfig eth0 +3.reboot</p> +</blockquote> +<hr> +<h4 id="问题三重启后ping命令不能使用因为dns还没设置编辑etcresolvconf加上dns服务器地址">问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。 +</h4><blockquote> +<p>设置好后,如果直接ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<pre><code>nameserver 8.8.8.8 +nameserver 8.8.4.4 +</code></pre> +<blockquote> +<p>这两个是Google提供的免费DNS服务器的IP地址</p> +</blockquote>x210开发板 虚拟驱动创建流程https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/cover.jpg" alt="Featured image of post x210开发板 虚拟驱动创建流程" /><h2 id="内核编译常用命令">内核编译常用命令 +</h2><p>安装模块 +<code>lsmod module_test.ko</code> +创建设备文件 +<code>mknod /dev/test c 250 0</code> +查看设备状态 +<code>lsmod module_test.ko</code> +查看设备注册信息(分为字符设备和块设备) +<code>cat /proc/devices</code></p> +<h2 id="知识补充">知识补充: +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span><span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">j</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:这里如果没有指定i值,则打印出来的是随机值 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 如果定义一个静态变量而没有赋值,则打印默认为0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="虚拟驱动创建流程">虚拟驱动创建流程 +</h2><p>首先进入x210_bsp/kernel</p> +<p>make menuconfig</p> +<p><img src="https://img-blog.csdnimg.cn/783c09aa06cb4a83a4df08d76d31c447.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/dc736c9d0d2b4ceaaaffcd6f90a1a16a.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/1193fb6e02be4c52a1d5951b0236ff38.png" +loading="lazy" +></p> +<p>make -j4</p> +<p>cp arch/arm/boot/zImage /tftpboot/ -f</p> +<p>重启开发板查看开发板设备</p> +<p>ls /sys/devices/platform/</p> +<p><img src="https://img-blog.csdnimg.cn/f57e4a58658e4380967bbfa1c0813864.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2f3b1acd43e740e68774ecbe2824ea2f.png" +loading="lazy" +></p> +<p>cd sys/class/leds</p> +<p>led_test_4编写完成后</p> +<p>编译不报错即可</p> +<p>cd /root/x210_bsp/kernel/drivers/leds/</p> +<p>cp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./</p> +<p>vi Makefile-&gt;</p> +<p><code>obj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o</code></p> +<p><img src="https://img-blog.csdnimg.cn/b30ce84418064d24a4e01c96218834f2.png" +loading="lazy" +></p> +<p>vi Kconfig更改依赖(添加以下文件)</p> +<p><code>config LEDS_S5PV210 tristate &quot;LED Support for S5PV210&quot; help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.</code></p> +<p><img src="https://img-blog.csdnimg.cn/43715e94bbcb4e8ab850492c919afc33.png" +loading="lazy" +></p> +<p>进入到x210_bsp/kernel</p> +<p>执行make menuconfig</p> +<p>可以发现生成了新的配置(Device Drivers-&gt; LED_Support),使能这个</p> +<p><img src="https://img-blog.csdnimg.cn/31b19678d8204209b05d62de54afd1d9.png" +loading="lazy" +></p> +<p>执行make编译</p> +<p><code> cp arch/arm/boot/zImage /tftpboot/ -f</code></p> +<p>secureCRT:</p> +<p>cd sys/class/leds</p> +<p>进入LED1,执行</p> +<p>echo 1 &gt; brightness // 灯亮</p> +<p>echo 0 &gt; brightness //灯灭</p> +<hr> +<p>最后附上源代码:</p> +<p><code>leds-s5pv210.c</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/module.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/init.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/fs.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/uaccess.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio-bank.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/regs-gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/ioport.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/io.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/cdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/device.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/leds.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED1 S5PV210_GPJ0(3) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED2 S5PV210_GPJ0(4) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED3 S5PV210_GPJ0(5) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_OFF 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_ON 0 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led1_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led1_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led2_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led2_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led3_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led3_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">s5pv210_led_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 申请GPIO +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="nf">gpio_request</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="s">&#34;led1_gpj0.3&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;gpio_request failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_direction_output</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led1&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led1_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led2&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led2_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led3&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led3_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">s5pv210_led_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">module_init</span><span class="p">(</span><span class="n">s5pv210_led_init</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">module_exit</span><span class="p">(</span><span class="n">s5pv210_led_exit</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_LICENSE</span><span class="p">(</span><span class="s">&#34;GPL&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_AUTHOR</span><span class="p">(</span><span class="s">&#34;WYQ&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_DESCRIPTION</span><span class="p">(</span><span class="s">&#34;module_test&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>Makefile</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#KERN_VER = $(shell uname -r) +</span></span></span><span class="line"><span class="cl"><span class="cp">#KERN_DIR = /lib/modules/$(KERN_VER)/build +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">KERN_DIR</span> <span class="o">=</span> <span class="o">/</span><span class="n">root</span><span class="o">/</span><span class="n">x210_bsp</span><span class="o">/</span><span class="n">kernel</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">obj</span><span class="o">-</span><span class="n">m</span> <span class="o">+=</span> <span class="n">leds</span><span class="o">-</span><span class="n">s5pv210</span><span class="p">.</span><span class="n">o</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">all</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nl">PHONY</span><span class="p">:</span><span class="n">clean</span> +</span></span><span class="line"><span class="cl"><span class="nl">clean</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> <span class="n">clean</span> +</span></span></code></pre></td></tr></table> +</div> +</div>线程间同步 信号量https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/Sun, 17 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/cover.jpg" alt="Featured image of post 线程间同步 信号量" /><h2 id="一概述">一、概述: +</h2><blockquote> +<p>多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:</p> +</blockquote> +<p><strong>信号量</strong>(semaphore)、<strong>互斥量</strong>(mutex)、和<strong>事件集</strong>(event)</p> +<h2 id="二信号量">二、信号量 +</h2><h4 id="1简述">1、简述 +</h4><p>信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到<code>同步</code>或<code>互斥</code>的目的。</p> +<p>信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当<code>信号量实例数目为零时</code>,再申请该信号量的线程就会被<code>挂起</code>在该信号量的等待队列上,等待可用的信号量实例(资源)。</p> +<p><img src="https://img-blog.csdnimg.cn/55d38f32e6e84b038d35a27bea1b9074.png" +loading="lazy" +></p> +<h4 id="2信号量结构体">2、信号量结构体 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_ipc_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; 继承自ipc_object类 */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">value</span><span class="p">;</span> <span class="cm">/**&lt; value of semaphore. */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">reserved</span><span class="p">;</span> <span class="cm">/**&lt; reserved field 预留*/</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。</p> +<h4 id="3信号量使用及管理">3、信号量使用及管理 +</h4><blockquote> +<p>对一个信号量的操作包含:<code>创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量</code>。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d8bde585ecaa4669817d29f0ffdc34f5.png" +loading="lazy" +></p> +<p>1)动态创建信号量</p> +<blockquote> +<p>当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。</p> +</blockquote> +<blockquote> +<p>当选择 <code>RT_IPC_FLAG_FIFO(先进先出)</code>方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; +当选择 <code>RT_IPC_FLAG_PRIO(优先级等待)</code>方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。</p> +</blockquote> +<p><code>函数声明</code>:</p> +<p><code>rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);</code></p> +<p><code>参数介绍</code>:</p> +<p><img src="https://img-blog.csdnimg.cn/f829de152967470393d8b7605e4c2b12.png" +loading="lazy" +></p> +<p><code>注意:</code></p> +<p><code>(1)此处的*name定义最多只能显示八个字符</code></p> +<p><code>(2)查看rt_sem_create()函数返回值是--&gt;typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore </code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// flag值 如下 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_FIFO 0x00 </span><span class="cm">/**&lt; FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_PRIO 0x01 </span><span class="cm">/**&lt; PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>2)动态创建的信号量删除</p> +<blockquote> +<p>系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。</p> +</blockquote> +<blockquote> +<p>调用这个函数时,系统将删除这个信号量。<code>如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。</code></p> +</blockquote> +<p><code>函数声明</code> +<code>rt_err_t rt_sem_delete(rt_sem_t sem);</code></p> +<p><code>实例</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)静态创建信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">value</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<p><img src="https://img-blog.csdnimg.cn/cbe2c704ffc849cf8859a6c46237681a.png" +loading="lazy" +></p> +<p>4)脱离信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于<code>静态初始化的信号量</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_detach</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>5)获取信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。</p> +<p>如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择<code>直接返回、或挂起等待一段时间、或永久等待</code>,直到其他线程或中断释放该信号量。</p> +<p>如果在参数 time 指定的时间内依然得不到信号量,线程将<code>超时返回</code>,返回值是<code> - RT_ETIMEOUT</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_take</span> <span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> <span class="kt">rt_int32_t</span> <span class="n">time</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// time参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_FOREVER -1 </span><span class="cm">/**&lt; Block forever until get resource. */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_NO 0 </span><span class="cm">/**&lt; Non-block. */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 扩展: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_trytake</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> <span class="c1">// 无等待获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>6)信号量释放</p> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>描述</code></p> +<blockquote> +<p>例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。</p> +</blockquote> +<h4 id="4信号量实例演示">4、信号量实例演示 +</h4><blockquote> +<p>这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/632591398002468c9a69cf3e4ac8cfe4.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/4293c61a10d14a128312fd50d7d2c9c6.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>查看信号量设定的标志位是<code>RT_IPC_FLAG_FIFO</code>,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1-&gt;线程2-&gt;线程1-&gt;线程2&hellip;的顺序执行的,这样就实现了线程的并发互斥运行。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1000730483a345728f1faa2ba68bde2d.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/31c3f295be2e41f9ab8d674ade353007.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>最后附上测试源代码</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> <span class="n">sem2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1</span><span class="p">,</span><span class="n">th2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th1_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">8000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="n">sem1</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">100</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th1_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="n">sem1</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="s">&#34;sem2&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_init successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th1</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th1&#34;</span><span class="p">,</span> <span class="n">th1_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th2</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th2&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th2</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>ubuntu彻底删除通过apt方式安装的程序https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post ubuntu彻底删除通过apt方式安装的程序" /><p>以删除apache2为例,其它程序也都是这么删&hellip;<br> +1.先通过apt删除程序和相关配置文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>2.自动删除不使用的软件包</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get autoremove +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.找出与apache2相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dpkg --get-selections|grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>没有就不显示,如果有就删除这些相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove xxx +</span></span></code></pre></td></tr></table> +</div> +</div><p>4.查看apache2是否还有进程存在</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ps -ef |grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果有就杀掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo kill -9 8888 //后面接pid号码,用空格隔开 +</span></span></code></pre></td></tr></table> +</div> +</div><p>5.全局查找和apache2相关的文件,需要一定时间,稍等</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo find / -name apache2* +</span></span></code></pre></td></tr></table> +</div> +</div><p>将找到的文件逐个删掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo rm -rf /usr/share/bash-completion/completions/apache2ctl +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就彻底删除掉apache2了</p>线程管理https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 线程管理" /><p>原理实战请查看<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124539095" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)</a></p> +<h1 id="一序言">一、序言 +</h1><p>在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 +同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。</p> +<p>下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:</p> +<blockquote> +<p>1.读取数据 +2.显示数据</p> +</blockquote> +<p>简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 +<img src="https://img-blog.csdnimg.cn/6d57696f2ffc4e859bf8c8c1ffc0789e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +在RT-Thread 中,与上述子任务对应的程序实体就是线程,<code>线程是实现任务的载体</code>。 +它是RT-Thread中<code>最基本的调度单位</code>,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的<code>优先级</code>,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 +<code>上下文:</code>当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。</p> +<h1 id="二线程管理的功能特点">二、线程管理的功能特点 +</h1><p>RT-Thread 线程管理的主要功能是<code>对线程进行管理和调度</code>,系统中总共存在两类线程,分别是<code>系统线程</code>和<code>用户线程</code>。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。</p> +<p>如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 +<img src="https://img-blog.csdnimg.cn/5584a47897de430597897d3a6bddd710.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>RT-Thread 的线程调度器是<code>抢占式</code>的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。</li> +<li>当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。</li> +<li>当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(<code>详细内容可参考</code><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124145153" target="_blank" rel="noopener" +>【操作系统】进程上下文和线程上下文</a>)信息恢复。</li> +</ul> +<h1 id="三线程的工作机制">三、线程的工作机制 +</h1><h2 id="1线程控制块">1.线程控制块 +</h2><p>在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* 线程控制块*/ +</span></span><span class="line"><span class="cl">struct rt_thread +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* rt 对象*/ +</span></span><span class="line"><span class="cl"> char name[RT_NAME_MAX]; /* 线程名称*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t type; /* 对象类型*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t flags; /* 标志位*/ +</span></span><span class="line"><span class="cl"> rt_list_t list; /* 对象列表*/ +</span></span><span class="line"><span class="cl"> rt_list_t tlist; /* 线程列表*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 栈指针与入口指针*/ +</span></span><span class="line"><span class="cl"> void *sp; /* 栈指针*/ +</span></span><span class="line"><span class="cl"> void *entry; /* 入口函数指针*/ +</span></span><span class="line"><span class="cl"> void *parameter; /* 参数*/ +</span></span><span class="line"><span class="cl"> void *stack_addr; /* 栈地址指针*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t stack_size; /* 栈大小*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 错误代码*/ +</span></span><span class="line"><span class="cl"> rt_err_t error; /* 线程错误代码*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t stat; /* 线程状态*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t current_priority; /* 当前优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t init_priority; /* 初始优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t number_mask; +</span></span><span class="line"><span class="cl"> ...... +</span></span><span class="line"><span class="cl"> rt_ubase_t init_tick; /* 线程初始化计数值*/ +</span></span><span class="line"><span class="cl"> rt_ubase_t remaining_tick; /* 线程剩余计数值*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> struct rt_timer thread_timer; /* 内置线程定时器*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t user_data; /* 用户数据*/ +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code> 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。</code></li> +<li><code>cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。</code></li> +<li><code>最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。</code></li> +</ul> +<h2 id="2线程的重要属性">2.线程的重要属性 +</h2><h4 id="1-线程栈">(1) 线程栈 +</h4><ul> +<li>RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。</li> +<li>线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。</li> +<li>对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。</li> +<li>线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 +<img src="https://img-blog.csdnimg.cn/041732b5e1fd43d5a62382931ad50360.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></li> +</ul> +<h4 id="2-线程状态">(2) 线程状态 +</h4><p>线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 +在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:</p> +<table> +<thead> +<tr> +<th>状态</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>初始态</td> +<td>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</td> +</tr> +<tr> +<td>就绪态</td> +<td>在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY</td> +</tr> +<tr> +<td>运行态</td> +<td>线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING</td> +</tr> +<tr> +<td>挂起态</td> +<td>也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND</td> +</tr> +<tr> +<td>关闭态</td> +<td>当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE</td> +</tr> +</tbody> +</table> +<h4 id="3-线程优先级">(3) 线程优先级 +</h4><ul> +<li> +<p>RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。</p> +</li> +<li> +<p>RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。</p> +</li> +</ul> +<h4 id="4-时间片">(4) 时间片 +</h4><blockquote> +<p>每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。</p> +</blockquote> +<p>假设有2 个<code>优先级相同的就绪态线程A 与B</code>,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 +<img src="https://img-blog.csdnimg.cn/31c4fb41bf8947c1a47864b12b9e602e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5-线程的入口函数">(5) 线程的入口函数 +</h4><p>线程控制块中的<code>entry</code>是线程的入口函数,它是线程实现预期功能的函数。</p> +<p>线程的入口函数由用户设计实现,一般有以下两种代码形式: +1.<code>无限循环模式</code></p> +<blockquote> +<p>在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 +界事件的发生,而后进行相应的服务:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void thread_entry(void* paramenter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">while (1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> /* 等待事件的发生*/ +</span></span><span class="line"><span class="cl"> /* 对事件进行服务、进行处理*/ +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 +所以在实时操作系统中必须注意的一点就是:<!-- raw HTML omitted -->线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。<!-- raw HTML omitted --></p> +</blockquote> +<p>2.<code>顺序执行或有限次循环模式</code></p> +<blockquote> +<p>如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">static void thread_entry(void* parameter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* 处理事务#1 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#2 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#3 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6-常见的线程错误码">(6) 常见的线程错误码 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_EOK 0 /* 无错误*/ +</span></span><span class="line"><span class="cl">#define RT_ERROR 1 /* 普通错误*/ +</span></span><span class="line"><span class="cl">#define RT_ETIMEOUT 2 /* 超时错误*/ +</span></span><span class="line"><span class="cl">#define RT_EFULL 3 /* 资源已满*/ +</span></span><span class="line"><span class="cl">#define RT_EEMPTY 4 /* 无资源*/ +</span></span><span class="line"><span class="cl">#define RT_ENOMEM 5 /* 无内存*/ +</span></span><span class="line"><span class="cl">#define RT_ENOSYS 6 /* 系统不支持*/ +</span></span><span class="line"><span class="cl">#define RT_EBUSY 7 /* 系统忙*/ +</span></span><span class="line"><span class="cl">#define RT_EIO 8 /* IO 错误*/ +</span></span><span class="line"><span class="cl">#define RT_EINTR 9 /* 中断系统调用*/ +</span></span><span class="line"><span class="cl">#define RT_EINVAL 10 /* 非法参数*/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3线程状态切换">3.线程状态切换 +</h2><p>RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: +<img src="https://img-blog.csdnimg.cn/3c79cc6198144f02b4830d4521384c30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<ul> +<li>线程通过调用函数<code>rt_thread_create/init()</code> 进入到初始状态<code>(RT_THREAD_INIT)</code>;</li> +<li>初始状态的线程通过调用函数<code>rt_thread_startup()</code> 进入到就绪状态<code>(RT_THREAD_READY)</code>;</li> +<li>就绪状态的线程被调度器调度后进入运行状态<code>(RT_THREAD_RUNNING)</code>;</li> +<li>当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态<code>(RT_THREAD_SUSPEND)</code>;</li> +</ul> +</blockquote> +<blockquote> +<ul> +<li>处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。</li> +<li>挂起状态的线程,如果调用<code>rt_thread_delete/detach() </code>函数,将更改为关闭状态<code>(RT_THREAD_CLOSE)</code>;</li> +<li>而运行状态的线程,如果运行结束,就会在线程的最后部分执行<code>rt_thread_exit() </code>函数,将状态更改为关闭状态。</li> +</ul> +</blockquote> +<p><!-- raw HTML omitted --><code>!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。</code></p> +<h2 id="4系统线程">4.系统线程 +</h2><p>系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。</p> +<h4 id="1空闲线程">(1)空闲线程 +</h4><p><code>空闲线程</code>是系统创建的最低优先级的线程,线程状态<code>永远为就绪态</code>。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。</p> +<p>另外,空闲线程在RT-Thread 也有着它的特殊用途:</p> +<ul> +<li>若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。</li> +<li>空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>钩子函数</a>和<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5ev7%5earticle_score_rank,157%5ev4%5econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>看门狗</a>不懂的可以看这里)</li> +</ul> +<h4 id="2-主线程">(2) 主线程 +</h4><p>在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。</p> +<p>过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 +<img src="https://img-blog.csdnimg.cn/b08911ca57334476945d473ab814f006.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="四线程的管理方式">四、线程的管理方式 +</h1><p>可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。</p> +<p>动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。</p> +<p>下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 +<img src="https://img-blog.csdnimg.cn/fea91f8134b648ccaefeb5cf201de15f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="1创建和删除线程">1.创建和删除线程 +</h2><h4 id="1创建线程">(1)创建线程 +</h4><p>一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_thread_t</span> <span class="n">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。</p> +</blockquote> +<p>线程创建rt_thread_create() 的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/f1ba4c76de384fcc91060025bff4bef7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2删除线程">(2)删除线程 +</h4><p>对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:</p> +<pre><code>rt_err_t rt_thread_delete(rt_thread_t thread); +</code></pre> +<p>调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。</p> +<p>线程删除rt_thread_delete() 接口的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/eb9a07efdd95454c8873506f5178d1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。</code></p> +<h2 id="2初始化和脱离线程">2.初始化和脱离线程 +</h2><h4 id="1初始化线程">(1)初始化线程 +</h4><p><code>线程的初始化</code>可以使用下面的函数接口完成,来初始化静态线程对象:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="n">rt_thread_init</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="n">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/c1e6ca6ef6b84ebe93d0888ff71332af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2脱离线程">(2)脱离线程 +</h4><p>对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:</p> +<pre><code>rt_err_t rt_thread_detach (rt_thread_t thread); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>thread</td> +<td>线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT_EOK</td> +<td>线程脱离成功</td> +</tr> +<tr> +<td>-RT_ERROR</td> +<td>线程脱离失败</td> +</tr> +</tbody> +</table> +<h2 id="3启动线程">3.启动线程 +</h2><p>创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:</p> +<pre><code>rt_err_t rt_thread_startup(rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/431f38ae0feb46dc833f9835ec57577e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 +动的线程优先级比当前线程优先级高,将立刻切换到这个线程。</p> +</blockquote> +<h2 id="4获得当前线程">4.获得当前线程 +</h2><p>在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:</p> +<pre><code>rt_thread_t rt_thread_self(void); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/33c1e79ddc8b42c0a28237a91e67b92c.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="5使线程出让处理器资源">5.使线程出让处理器资源 +</h2><blockquote> +<p>当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。</p> +</blockquote> +<p>线程让出处理器使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_yield(void); +</code></pre> +<blockquote> +<p>调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。</p> +</blockquote> +<h2 id="6使线程睡眠">6.使线程睡眠 +</h2><blockquote> +<p>在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。</p> +</blockquote> +<p>线程睡眠可使用以下三个函数接口:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_thread_sleep(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_delay(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_mdelay(rt_int32_t ms); +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/6ebefaeea61f48a7b26d43e0d6589055.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="7挂起和恢复线程">7.挂起和恢复线程 +</h2><h4 id="1线程挂起">(1)线程挂起 +</h4><blockquote> +<ul> +<li>当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。</li> +<li>处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。</li> +</ul> +</blockquote> +<p><code>线程挂起</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_suspend (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/eed2dcfd794040798637c029b253fb87.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。</code></p> +<h4 id="2恢复线程">(2)恢复线程 +</h4><blockquote> +<p>恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 +所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。</p> +</blockquote> +<p><code>线程恢复</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_resume (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/0640fc789a1645d3b424f605d3aca937.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="8控制线程">8.控制线程 +</h2><p>当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:</p> +<pre><code>rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/348eb561864549528d9695d8f504af92.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<pre><code>指示控制命令cmd 当前支持的命令包括: +•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级; +•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用; +•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。 +</code></pre> +<h2 id="设置和删除空闲钩子">设置和删除空闲钩子 +</h2><blockquote> +<p>空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。</p> +</blockquote> +<p>设置/ 删除空闲钩子的接口如下:</p> +<pre><code>rt_err_t rt_thread_idle_sethook(void (*hook)(void)); +rt_err_t rt_thread_idle_delhook(void (*hook)(void)); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>设置/删除的钩子函数</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT-EOK</td> +<td>设置/删除成功</td> +</tr> +<tr> +<td>-RT_EFULL</td> +<td>设置失败</td> +</tr> +<tr> +<td>-RT_ENOSYS</td> +<td>删除失败</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。</code></p> +<h2 id="10设置调度器钩子">10.设置调度器钩子 +</h2><p><code>在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。</code></p> +<p>在系统线程切换时,这个钩子函数将被调用:</p> +<pre><code>void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); +</code></pre> +<p><code>设置调度器钩子函数的输入参数</code>如下表所示:</p> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>表示用户定义的钩子函数指针</td> +</tr> +</tbody> +</table> +<p><code>钩子函数hook() 的声明</code>如下:</p> +<pre><code>void hook(struct rt_thread* from, struct rt_thread* to); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>from</td> +<td>表示系统所要切换出的线程控制块指针</td> +</tr> +<tr> +<td>to</td> +<td>表示系统所要切换到的线程控制块指针</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。</code></p> +<hr> +<p>资料参考: +(1)<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5Ev7%5Earticle_score_rank,157%5Ev4%5Econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>【STM32】HAL库 STM32CubeMX教程五&mdash;-看门狗(独立看门狗,窗口看门狗)</a> +(2)<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>什么是钩子函数</a> +(3)<a class="link" href="https://www.rt-thread.org/document/site/#/" target="_blank" rel="noopener" +>RT-Thread文档中心</a></p>I2C(内核学习)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post I2C(内核学习)" /><h2 id="一i2c协议">一、i2c协议 +</h2><p>由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。</p> +<h2 id="二i2c物理层">二、i2c物理层 +</h2><ul> +<li> +<p>i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 +<code>SDA</code>:用于传输数据 +<code>SCL</code>:用于同步数据收发</p> +</li> +<li> +<p>每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问</p> +</li> +<li> +<p>i2c支持多主控,任何时间点都只能有一个主控。 +<img src="https://img-blog.csdnimg.cn/01cc1805f0db4842a836a7dae9b11978.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +</li> +<li> +<p>i2c器件的SDA引脚和SCL引脚是开漏电路<a class="link" href="https://blog.csdn.net/ngulb/article/details/81174233?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E5%BC%80%E6%BC%8F%E7%94%B5%E8%B7%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81174233.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>形式,因此,SDA和SCL总线都需要连接上拉电阻<a class="link" href="https://blog.csdn.net/fymx203/article/details/89426403?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164973690016782092947037%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164973690016782092947037&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-89426403.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E4%B8%8A%E6%8B%89%E7%94%B5%E9%98%BB&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>,当总线空闲时,两条总线均为高电平。</p> +</li> +<li> +<p>各器件的SDA和SCL信号线在总线上都是<code>线与</code>关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)</p> +</li> +</ul> +<h2 id="三i2c协议层">三、i2c协议层 +</h2><p>协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。</p> +<h4 id="1i2c总线的位传输">1.i2c总线的位传输 +</h4><p>数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 +数据改变:当SCL为低电平时,SDA才可以改变电平 +<code>i2c位传输时序图</code> +<img src="https://img-blog.csdnimg.cn/3bcc9522f82841b5a9808703e4c29fa9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2i2c总线的开始和结束信号">2.i2c总线的开始和结束信号 +</h4><p><code>开始信号</code>:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 +<code>结束信号</code>:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。</p> +<h4 id="3i2c应答信号">3.i2c应答信号 +</h4><ul> +<li>在<code>主机</code>发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答<code>ACK</code>(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)</li> +<li>当<code>从机</code>接收不到数据或通信故障时,<code>从机</code>必须使SDA保持高电平,<code>主机</code>产生一个结束信号终止传输或者产生新的传输。</li> +</ul> +<h4 id="4i2c总线的仲裁机制">4.i2c总线的仲裁机制 +</h4><ul> +<li>SDA的仲裁也是建立在总线具有<code>线与</code>逻辑功能的原理上的。</li> +<li>节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。</li> +<li>SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)</li> +<li>当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是<code>线与</code>连接。</li> +</ul> +<h2 id="四访问i2c总线设备">四、访问i2c总线设备 +</h2><p>一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:</p> +<table> +<thead> +<tr> +<th>函数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>rt_device_find()</td> +<td>根据I2C 总线设备名称查找设备获取设备<a class="link" href="https://blog.csdn.net/wyx0224/article/details/83385168?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164976053816780265492902%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164976053816780265492902&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-83385168.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E5%8F%A5%E6%9F%84&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>句柄</a></td> +</tr> +<tr> +<td>rt_i2c_transfer()</td> +<td>传输数据</td> +</tr> +</tbody> +</table> +<h2 id="五查找i2c总线设备">五、查找i2c总线设备 +</h2><p>在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,</p> +<pre><code>rt_device_t rt_device_find(const char* name); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td>i2c总线设备名称</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>&ndash;</td> +</tr> +<tr> +<td>设备句柄</td> +<td>查找到对应设备将返回相应的设备句柄</td> +</tr> +<tr> +<td>RT-NULL</td> +<td>没有找到相应的设备对象</td> +</tr> +</tbody> +</table> +<p>一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六数据传输">六、数据传输 +</h2><p>获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs[], +</span></span><span class="line"><span class="cl"> rt_uint32_t num); +</span></span></code></pre></td></tr></table> +</div> +</div><table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>bus</td> +<td>i2c总线设备句柄</td> +</tr> +<tr> +<td>msgs[]</td> +<td>待传输的消息数组指针</td> +</tr> +<tr> +<td>num</td> +<td>消息数组的元素个数</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>-</td> +</tr> +<tr> +<td>-</td> +<td>-</td> +</tr> +<tr> +<td>消息数组的元素个数</td> +<td>成功</td> +</tr> +<tr> +<td>错误码</td> +<td>失败</td> +</tr> +</tbody> +</table> +<ul> +<li>和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。</li> +<li>参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 +<code>!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。</code></li> +</ul> +<blockquote> +<p>I2C 消息数据结构原型如下:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct rt_i2c_msg +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">rt_uint16_t addr; /* 从机地址*/ +</span></span><span class="line"><span class="cl">rt_uint16_t flags; /* 读、写标志等*/ +</span></span><span class="line"><span class="cl">rt_uint16_t len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl">rt_uint8_t *buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。</li> +<li>标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 +<code>!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_I2C_WR 0x0000 /* 写标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_RD (1u &lt;&lt; 0) /* 读标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_ADDR_10BIT (1u &lt;&lt; 2) /* 10 位地址模式*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_START (1u &lt;&lt; 4) /* 无开始条件*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_IGNORE_NACK (1u &lt;&lt; 5) /* 忽视NACK */ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_READ_ACK (1u &lt;&lt; 6) /* 读的时候不发送ACK */ +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>使用示例如下所示:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">#define AHT10_ADDR 0x38 /* 从机地址*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 读传感器寄存器数据*/ +</span></span><span class="line"><span class="cl">static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t +</span></span><span class="line"><span class="cl">*buf) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs; +</span></span><span class="line"><span class="cl"> msgs.addr = AHT10_ADDR; /* 从机地址*/ +</span></span><span class="line"><span class="cl"> msgs.flags = RT_I2C_RD; /* 读标志*/ +</span></span><span class="line"><span class="cl"> msgs.buf = buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl"> msgs.len = len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl"> /* 调用I2C设备接口传输数据*/ +</span></span><span class="line"><span class="cl"> if (rt_i2c_transfer(bus, &amp;msgs, 1) == 1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return RT_EOK; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return -RT_ERROR; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七i2c-总线设备使用示例">七、I2C 总线设备使用示例 +</h2><p>I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:</p> +<ol> +<li>首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。</li> +<li>控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() +这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">/*</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序清单:</span> <span class="err">这是一个</span><span class="n">I2C</span> <span class="err">设备使用例程</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">例程导出了</span><span class="n">i2c_aht10_sample</span> <span class="err">命令到控制终端</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令调用格式:</span> <span class="n">i2c_aht10_sample</span> <span class="n">i2c1</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令解释:</span> <span class="err">命令第二个参数是要使用的</span><span class="n">I2C总线设备名称</span><span class="err">,</span> <span class="err">为空则使用默认的</span><span class="n">I2C总线设备</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序功能:</span> <span class="err">通过</span><span class="n">I2C</span> <span class="err">设备读取温湿度传感器</span><span class="n">aht10</span> <span class="err">的温湿度数据并打印</span> +</span></span><span class="line"><span class="cl"><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtdevice.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_ADDR 0x38 /* 从机地址*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_GET_DATA 0xAC /* 获取数据命令*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">i2c_bus</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> <span class="o">/*</span> <span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_bool_t</span> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_FALSE</span><span class="p">;</span> <span class="o">/*</span> <span class="err">传感器初始化状态</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">写传感器寄存器</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">write_reg</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">reg</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">reg</span><span class="p">;</span> <span class="o">//</span><span class="n">cmd</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_WR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">读传感器寄存器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">read_regs</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">len</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">buf</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_RD</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">read_temp_humi</span><span class="p">(</span><span class="ne">float</span> <span class="o">*</span><span class="n">cur_temp</span><span class="p">,</span> <span class="ne">float</span> <span class="o">*</span><span class="n">cur_humi</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_GET_DATA</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">/*</span> <span class="err">发送命令</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_regs</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> <span class="o">/*</span> <span class="err">获取传感器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">湿度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_humi</span> <span class="o">=</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">12</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span> <span class="o">|</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf0</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">*</span> <span class="mf">100.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span><span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">温度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_temp</span> <span class="o">=</span> <span class="p">((</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="o">*</span> <span class="mf">200.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">)</span><span class="o">-</span> <span class="mi">50</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">aht10_init</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">查找</span><span class="n">I2C总线设备</span><span class="err">,</span> <span class="err">获取</span><span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">i2c_bus</span> <span class="o">=</span> <span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="p">)</span><span class="n">rt_device_find</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i2c_bus</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;can&#39;t find </span><span class="si">%s</span><span class="s2"> device!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_NORMAL_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x08</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_CALIBRATION_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_TRUE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">i2c_aht10_sample</span><span class="p">(</span><span class="ne">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">char</span> <span class="n">name</span><span class="p">[</span><span class="n">RT_NAME_MAX</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">AHT10_I2C_BUS_NAME</span><span class="p">,</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">传感器初始化</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">aht10_init</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">读取温湿度数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_temp_humi</span><span class="p">(</span><span class="o">&amp;</span><span class="n">temperature</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor humidity : </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2"> </span><span class="si">%%</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span> <span class="n">temperature</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="o">-</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;initialize sensor failed!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">导出到</span><span class="n">msh</span> <span class="err">命令列表中</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">i2c_aht10_sample</span><span class="p">,</span> <span class="n">i2c</span> <span class="n">aht10</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>学习资料参考:<a class="link" href="https://item.jd.com/10022312146340.html" target="_blank" rel="noopener" +>《嵌入式系统设计》</a>、<a class="link" href="https://club.rt-thread.org/index.html" target="_blank" rel="noopener" +>RT-Thread</a></p>RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/cover.jpg" alt="Featured image of post RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)" /><h2 id="一初识rt-thread">一、初识RT-Thread +</h2><p><code>做世界级的 OS,让万物互联,信息畅通无阻。</code> +<code>成为未来 AIoT 领域最为主流的操作系统平台。</code></p> +<h4 id="1简介">1.简介 +</h4><blockquote> +<p>RT-Thread 是一个集<code>实时操作系统(RTOS)内核、中间件组件和开发者社区于一体</code>的技术平台,由<code>熊谱翔先生</code>带领并集合开源社区力量开发而成,RT-Thread 也是一个<code>组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性</code>的<code>物联网操作系统</code>。</p> +</blockquote> +<h4 id="2前景">2.前景 +</h4><blockquote> +<p>RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个<code>国内最大的嵌入式开源社区</code>,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人<code>自主开发</code>、国内最成熟稳定和装机量最大的<code>开源 RTOS</code>。</p> +</blockquote> +<h4 id="3软件生态">3.软件生态 +</h4><blockquote> +<p>RT-Thread 拥有<code>良好的软件生态</code>,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。</p> +</blockquote> +<h2 id="二实验准备">二、实验准备 +</h2><ul> +<li>编程工具:<code>RT-Thread studio</code></li> +<li>开发板:<code>潘多拉STM32L475</code></li> +</ul> +<hr> +<h2 id="三实验需求">三、实验需求 +</h2><ul> +<li>1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 +右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。</li> +<li>2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。</li> +</ul> +<h2 id="四操作流程">四、操作流程 +</h2><h4 id="1新建rt-thread工程">1.新建RT-Thread工程 +</h4><p><img src="https://img-blog.csdnimg.cn/85370c1057554323ba75dd83c3d1844f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rt-thread-studio界面介绍">2.RT-Thread Studio界面介绍 +</h4><p><img src="https://img-blog.csdnimg.cn/b24064da660f40b5b00e9e0f03d4f1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="3代码编写">3.代码编写 +</h4><p><img src="https://img-blog.csdnimg.cn/c556436b0d44443686dafa3a0f389bd5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="4烧录">4.烧录 +</h4><p><img src="https://img-blog.csdnimg.cn/c5ea1524e61e4b92af667e17decd12bb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5串口监视">5.串口监视 +</h4><p><img src="https://img-blog.csdnimg.cn/eae3d5a76ae14aa0a7e6a2d00145024d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="五代码演示">五、代码演示 +</h2><p><code>1.头文件</code></p> +<pre><code>#include &lt;rtthread.h&gt; +#include &lt;rtdevice.h&gt; +#include &lt;board.h&gt; +</code></pre> +<p><code>2.宏定义</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">//</span><span class="err">按键初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">电机初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">蜂鸣器初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_BEEP GET_PIN(B,2)//PB2:BEEP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">enum</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_STOP</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_LEFT</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_RIGHT</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>3.void motor_ctrl(rt_uint8_t turn) //电机控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void motor_ctrl(rt_uint8_t turn) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (turn == MOTOR_STOP) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_LEFT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_RIGHT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_HIGH); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;err parameter ! Please enter 0-2.&#34;); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void beep_ctrl(rt_uint8_t on) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (on) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.void irq_callback(void *args) // 中断回调函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void irq_callback(void *args) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> rt_uint32_t sign = (rt_uint32_t)args; +</span></span><span class="line"><span class="cl"> switch (sign) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> case PIN_KEY0: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_LEFT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY0 interrupt. motor turn left.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY1: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_RIGHT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY1 interrupt. motor turn right.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY2: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_STOP); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY2 interrupt. motor stop.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> default: +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;error sign= %d !&#34;, sign); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> unsigned int count = 1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置电机控制引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置蜂鸣器引脚为输出模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键中断模式与中断回调函数*/ +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 使能中断*/ +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> while (count &gt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(50); +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;WK_UP pressed. beep on.&#34;); +</span></span><span class="line"><span class="cl"> beep_ctrl(1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> beep_ctrl(0); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(10); +</span></span><span class="line"><span class="cl"> count++; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六原理讲解">六、原理讲解 +</h2><p><!-- raw HTML omitted -->通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 +1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 +2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。<!-- raw HTML omitted --></p> +<table> +<thead> +<tr> +<th>按键</th> +<th>功能</th> +</tr> +</thead> +<tbody> +<tr> +<td>KEY0</td> +<td>电机左转</td> +</tr> +<tr> +<td>KEY1</td> +<td>电机右转</td> +</tr> +<tr> +<td>KEY2</td> +<td>电机停止</td> +</tr> +<tr> +<td>WK_UP</td> +<td>蜂鸣器响</td> +</tr> +</tbody> +</table>RT-Thread Studio使用 2.内核实战篇(线程)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/cover.jpg" alt="Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)" /><p>详细原理参考:<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<h2 id="一线程创建">一、线程创建 +</h2><h4 id="1函数原型">1、函数原型 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 线程创建 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_thread_t</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>首先我们来看看线程创建函数返回值类型:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/de83fe0a4aad4ffe9989eacdf86e96df.png" +loading="lazy" +></p> +<blockquote> +<p>可以看到线程创建函数的返回值类型为:<code>rt_thread_t</code>,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1dfc5d7964484cae9cc44d8067ffcdd0.png" +loading="lazy" +></p> +<h4 id="2线程定义">2、线程定义 +</h4><p>那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1_ptr</span> <span class="o">=</span> <span class="nb">NULL</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>接下来就是我们给进程控制块传参了</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/90d481586b964d01958c9a14a2bd4695.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/7f39dba639bb4c5faeed06524f57a60d.png" +loading="lazy" +></p> +<h4 id="3线程创建判断">3、线程创建判断 +</h4><p>由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功</p> +<p>我们先来看下线程返回值(如下图)</p> +<blockquote> +<p>如果<code>成功创建</code>的话,返回值是会返回我们所创建的线程对象的</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b19a07990b2240728d423f2c7064d47c.png" +loading="lazy" +></p> +<blockquote> +<p>如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/faf3ad30a6f046638db1c77a0c8275a4.png" +loading="lazy" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span><span class="p">(</span><span class="n">th1_ptr</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//错误信息打印 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_thread_create create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> <span class="c1">// 设定当线程th1_ptr创建失败后,返回一个空间不足的标志 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">//打印debug调试信息 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_thread_create create successed ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4线程入口函数">4、线程入口函数 +</h4><p>我们在线程的入口处理函数写一个循环函数:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源</code></p> +<ul> +<li>编译,串口观察</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4c5556830c644e48bfa76008218fb680.png" +loading="lazy" +></p> +<p>由于RTT studio有内置的串口终端,我们直接打开</p> +<p><img src="https://img-blog.csdnimg.cn/cd4fd4b573c0421a88a73d9f8e7160dd.png" +loading="lazy" +></p> +<p>终端输入list_thread可以查看所有的线程</p> +<p><img src="https://img-blog.csdnimg.cn/edae1f6480c54759915145477406f17d.png" +loading="lazy" +></p> +<h4 id="5总结">5、总结 +</h4><p>这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?</p> +<p>其实我们再看th_demo线程的状态可以看到是<code>init</code>,参考<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<p><code>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</code></p> +<p>其实这句话就表明当<code>线程处于初始化状态下是不参与系统调度</code>的!</p> +<h4 id="6补充">6、补充 +</h4><p>线程错误码:</p> +<p><img src="https://img-blog.csdnimg.cn/f32f5440cb604b2d8eea4a4546d977b0.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<h2 id="二线程启动">二、线程启动 +</h2><p>函数原型</p> +<p>在主函数中加入命令,使线程进入就绪态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_thread_startup(th1_ptr); +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为<code>挂起态</code></p> +<p><img src="https://img-blog.csdnimg.cn/f5f40f386046488f89e56ab8ee8db6d4.png" +loading="lazy" +></p> +<p><code>解释:</code>虽然我们调用<code>rt_thread_startup</code>函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了<code>rt_thread_mdelay</code>函数使其有一定时间的休眠,从而进入了挂起态`</p> +<h2 id="三初始化线程">三、初始化线程 +</h2><p><code>rt_thread_init</code></p> +<h4 id="1函数声明">1、函数声明 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 模板函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_err_t</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="k">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="kr">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2函数定义">2、函数定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th2</span><span class="p">,</span><span class="s">&#34;th2_demo&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">th2_stack</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">th2_stack</span><span class="p">),</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>此处我们需要定义一个ret整型变量用于<code>rt_thread_init</code>的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b7ce209e742948a398d235d4fd799279.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/06a57b94d88c4cdf97f9a431d1578862.png" +loading="lazy" +></p> +<h4 id="3线程入口函数">3、线程入口函数 +</h4><p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">10</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4判断创建状态">4、判断创建状态 +</h4><p>静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用<code>rt_thread_startup</code>函数使线程2进入就绪态,并执行线程处理函数。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">if(ret &lt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> LOG_E(&#34;rt2_thread_create create failed ...\n&#34;); // 错误信息打印 +</span></span><span class="line"><span class="cl"> return ret; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> LOG_D(&#34;rt_thread2_create create successes ...\n&#34;); +</span></span><span class="line"><span class="cl"> rt_thread_startup(&amp;th2); // 创建成功后,我们开启线程,使其进入就绪态 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启</p> +</blockquote> +<h4 id="5实验结果">5、实验结果 +</h4><blockquote> +<p>分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/861754f210a74896a6d63d20fbb629f0.png" +loading="lazy" +></p> +<blockquote> +<p>线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/85333e4d1b1942d6a59b10e528797ecc.png" +loading="lazy" +></p>ubuntu安装交叉编译工具链https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/cover.jpg" alt="Featured image of post ubuntu安装交叉编译工具链" /><h1 id="ubuntu安装交叉编译工具链附避坑指南">ubuntu安装交叉编译工具链(附避坑指南) +</h1><blockquote> +<p>1.打开Ubuntu,在终端进入/usr/local/目录下</p> +</blockquote> +<pre><code>cd /usr/local/ +</code></pre> +<blockquote> +<p>2.在local/目录下创建一个名为arm的文件夹</p> +</blockquote> +<pre><code>mkdir arm +</code></pre> +<blockquote> +<p>3.在自己的共享文件夹下找到<a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a>,并复制到之前创建的arm目录下</p> +</blockquote> +<pre><code>cp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/ +</code></pre> +<blockquote> +<p>4.进入到arm目录下,解压该其中文件</p> +</blockquote> +<pre><code>cd /usr/local/arm +tar -jxvf arm-2009q3.tar.bz2 +</code></pre> +<blockquote> +<p>5.然后执行:</p> +</blockquote> +<pre><code>cd arm-2009q3/bin +./arm-none-linux-gnueabi-gcc -v +</code></pre> +<p><code>注意:</code><!-- raw HTML omitted -->这里如果输入<code>./arm-none-linux-gnueabi-gcc -v</code>终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持</p> +<pre><code>sudo apt-get install libc6:i386 +</code></pre> +<p><!-- raw HTML omitted -->安装好了之后重新输入<code>./arm-none-linux-gnueabi-gcc -v</code> +<img src="https://img-blog.csdnimg.cn/b0660902aed64a88a257ed92b892b8f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<!-- raw HTML omitted -->操作成功!</p> +<blockquote> +<p>6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 +打开配置文件</p> +</blockquote> +<pre><code>sudo vim /etc/profile +</code></pre> +<blockquote> +<p>7.在vi界面末尾处加入</p> +</blockquote> +<pre><code>export PATH=$PATH:/usr/local/arm/arm-2009q3/bin +</code></pre> +<blockquote> +<p>8.回到主目录,查看交叉编译工具是否可用</p> +</blockquote> +<pre><code>cd ~ +source /etc/profile +</code></pre> +<p><code>注</code> <!-- raw HTML omitted -->这里如果没有出现相关信息,切换root用户再次输入命令</p> +<p>使用 <code>echo $PATH</code>查看交叉编译链的安装路径是否加入了环境变量。 +使用<code>arm-linux-gnueabihf-gcc -v</code>测试交叉编译链是否好使</p> +<blockquote> +<p>9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:</p> +</blockquote> +<pre><code>chmod 777 mk-arm-linux-.sh +./mk-arm-linux-.sh +</code></pre> +<p><code>这里由于运行时报错,原因详见</code><a class="link" href="https://blog.csdn.net/LWJdear/article/details/79868551?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=bash:%20./mk-arm-linux-.sh:%20Perm&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-79868551.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>解决linux的-bash: ./xx.sh: Permission denied</a></p> +<blockquote> +<p>ls查看,可以发现符号链接出现,到此,交叉编译链配置成功!</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/6dc86a581621467d8639643cc154877a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p><code>附件</code>:</p> +<ul> +<li> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a></p> +</li> +<li> +<p><code>mk-arm-linux-.sh脚本文件</code></p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ar -s arm-linux-ar +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-as -s arm-linux-as +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++ -s arm-linux-c++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-g++ -s arm-linux-g++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1 +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ld -s arm-linux-ld +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-nm -s arm-linux-nm +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-size -s arm-linux-size +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strings -s arm-linux-strings +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strip -s arm-linux-strip +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<p><code>有问题欢迎评论留言致信:</code><a class="link" href="https://blog.csdn.net/qq_56914146?type=blog" target="_blank" rel="noopener" +>blogs</a></p>ubuntu桌面恢复(20.04)https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/<img src="https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/cover.jpg" alt="Featured image of post ubuntu桌面恢复(20.04)" /><h3 id="恢复ubuntu2004默认桌面管理器">恢复ubuntu20.04默认桌面管理器 +</h3><ul> +<li> +<ul> +<li> +<ul> +<li><a class="link" href="#GDM_KDM_LightDM_SDDM_5" >一、GDM, KDM, LightDM, SDDM的区别和安装配置</a></li> +<li> +<ul> +<li><a class="link" href="#1GDMgnome_8" >1、GDM,gnome系列的图形管理器</a></li> +<li><a class="link" href="#2KDMSDDMKDE_17" >2、KDM,SDDM是KDE系列的图形管理器</a></li> +<li><a class="link" href="#3LightDM_27" >3、LightDM</a></li> +</ul> +</li> +<li><a class="link" href="#_37" >二、配置和切换</a></li> +<li><a class="link" href="#ubuntu2004_62" >三、恢复ubuntu20.04默认桌面管理器</a></li> +<li> +<ul> +<li><a class="link" href="#1_65" >1、打开终端,用管理员口令下载相关资源</a></li> +<li><a class="link" href="#2gnomeshell_71" >2、安装gnome-shell</a></li> +<li><a class="link" href="#3ubuntugnomedesktop_80" >3、安装ubuntu-gnome-desktop</a></li> +<li><a class="link" href="#4unitytweaktoolgnometweaktool_85" >4、安装unity-tweak-tool和gnome-tweak-tool</a></li> +<li><a class="link" href="#5_94" >5、安装完成后重启</a></li> +</ul> +</li> +</ul> +</li> +</ul> +</li> +</ul> +<p>起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能<a class="link" href="https://blog.csdn.net/irober/article/details/112608610" target="_blank" rel="noopener" +>远程控制桌面</a>了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(<strong>gnome图形管理器</strong>)也变成了我不喜欢的风格(<strong>轻量级的LightDM</strong>)了,大家以后要慎重。<br> +注意:我是个半吊子,仅供参考。</p> +<h3 id="一gdm-kdm-lightdm-sddm的区别和安装配置">一、GDM, KDM, LightDM, SDDM的区别和安装配置 +</h3><p><a class="link" href="https://blog.csdn.net/u014466109/article/details/105572470" target="_blank" rel="noopener" +>GDM, KDM, LightDM, SDDM的区别和安装配置</a><br> +<strong>gdm3,kdm 和 lightdm</strong> 都是显示管理器。 它们提供图形化登录并处理用户身份验证。</p> +<h4 id="1gdmgnome系列的图形管理器">1、GDM,gnome系列的图形管理器 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2kdmsddm是kde系列的图形管理器">2、KDM,SDDM是KDE系列的图形管理器 +</h4><p>kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3lightdm">3、LightDM +</h4><p>LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="二配置和切换">二、配置和切换 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。</p> +<p>要检查当前正在使用的显示管理器,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cat</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">X11</span><span class="o">/</span><span class="n">default</span><span class="o">-</span><span class="n">display</span><span class="o">-</span><span class="n">manager</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。</p> +<h3 id="三恢复ubuntu2004默认桌面管理器">三、恢复ubuntu20.04默认桌面管理器 +</h3><p><a class="link" href="https://www.zhihu.com/tardis/sogou/art/27659651" target="_blank" rel="noopener" +>恢复ubuntu20.04默认桌面管理器</a><br> +目前Ubuntu的主流桌面<strong>GNOME</strong>, Ubntu的内置桌面是<strong>Untiy</strong></p> +<h4 id="1打开终端用管理员口令下载相关资源">1、打开终端,用管理员口令下载相关资源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">Ctrl</span><span class="o">+</span><span class="n">Alt</span><span class="o">+</span><span class="n">T</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开终端,用管理员口令下载相关资源</p> +<h4 id="2安装gnome-shell">2、安装gnome-shell +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">shell</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<p>管理员权限需要输入密码,但是系统不会显示你输入的密码<br> +输入完成后,直接回车即可</p> +<h4 id="3安装ubuntu-gnome-desktop">3、安装ubuntu-gnome-desktop +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">ubuntu</span><span class="o">-</span><span class="n">gnome</span><span class="o">-</span><span class="n">desktop</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装unity-tweak-tool和gnome-tweak-tool">4、安装unity-tweak-tool和gnome-tweak-tool +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">unity</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5安装完成后重启">5、安装完成后重启 +</h4><p>然后一切恢复如初,仿佛没发生过。</p>x11vnc安装与配置https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/<img src="https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/cover.jpg" alt="Featured image of post x11vnc安装与配置" /><h1 id="1-安装x11vnc">1. 安装x11vnc +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install x11vnc -y +</span></span></code></pre></td></tr></table> +</div> +</div><p>直接安装成功。</p> +<h1 id="2-设置vnc密码">2. 设置vnc密码 +</h1><p>密码存储在/etc/目录里面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo x11vnc -storepasswd /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><p>放在这个位置,需要设置文件读取权限<br> +否则会提示密码校验失败</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><h1 id="3创建vnc配置文件">3.创建vnc配置文件 +</h1><p>在/etc/init 下创建一个x11vnc.conf的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> <span class="nb">cd</span> /etc/init +</span></span><span class="line"><span class="cl"> sudo gedit x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>文件内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#description &#34;xiaoqiang vnc server&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#start on runlevel [2345]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#stop on runlevel [06]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#script</span> +</span></span><span class="line"><span class="cl"> <span class="nb">exec</span> /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport <span class="m">5900</span> -shared +</span></span><span class="line"><span class="cl"><span class="c1">#end script</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。</p> +<h1 id="4启动vnc服务">4.启动vnc服务 +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/12b8d37ebfbb4160a7d50196cf3bd2b7.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了</p> +<h1 id="5设置自启动">5.设置自启动 +</h1><p>我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。</p> +<h2 id="1首先编写一个脚本">(1)首先编写一个脚本 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gedit x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>添加以下内容<br> +第一行是要添加的解释器,后面是要执行的指令内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>防止误删,从home移动到/etc/init.d/文件夹中<br> +并添加权限</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mv x11vnc.sh /etc/init.d/ +</span></span><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2添加启动项">(2)添加启动项 +</h2><p>点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。<br> +<img src="https://img-blog.csdnimg.cn/b1f7234307b64d9ca6844704a100a243.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +点击右侧添加,添加自动启动项。<br> +<img src="https://img-blog.csdnimg.cn/fd2f7303980f4e7598e7f4ce6950ef20.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +添加内容如下;重要的是第二行,</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bash /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>用bash启动才能成功,保存之后重启,确实可以开机自启了。<br> +<img src="https://img-blog.csdnimg.cn/caa1005977844d8baffbba60e7d6ea93.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="6x11vnc配置安装虚拟显卡驱动">6.x11vnc配置(安装虚拟显卡驱动) +</h1><p>如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示</p> +<h2 id="1首先还是安装命令">(1)首先还是安装命令 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install xserver-xorg-video-dummy +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2接下来就是创建配置文件-etcx11xorgconf">(2)接下来就是创建配置文件 <code>/etc/X11/xorg.conf</code> +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Section &#34;Device&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> Driver &#34;dummy&#34; +</span></span><span class="line"><span class="cl"> VideoRam 64000 +</span></span><span class="line"><span class="cl"> Option &#34;IgnoreEDID&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl"> Option &#34;NoDDC&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> HorizSync 15.0-100.0 +</span></span><span class="line"><span class="cl"> VertRefresh 15.0-200.0 +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Monitor &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Device &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> DefaultDepth 24 +</span></span><span class="line"><span class="cl"> SubSection &#34;Display&#34; +</span></span><span class="line"><span class="cl"> Depth 24 +</span></span><span class="line"><span class="cl"> Modes &#34;1280x720&#34; +</span></span><span class="line"><span class="cl"> EndSubSection +</span></span><span class="line"><span class="cl">EndSection +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3再修改个文件加点配置">(3)再修改个文件加点配置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /boot/firmware/usercfg.txt +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">framebuffer_width=1280 +</span></span><span class="line"><span class="cl">framebuffer_height=720 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>如果想要恢复显示器的连接,可以先使用ssh访问终端并将<code>/etc/X11/xorg.conf</code>这个文件删除,再次重启即可</strong></p>时钟管理(原理+实战)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/Wed, 13 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/cover.jpg" alt="Featured image of post 时钟管理(原理+实战)" /><h2 id="一时钟节拍">一、时钟节拍 +</h2><p>任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。</p> +<p>RT-Thread 中,时钟节拍的长度可以根据 <code>RT_TICK_PER_SECOND</code> 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,<code>系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!</code></p> +<p>rtconfig.h配置文件中定义:</p> +<blockquote> +<ul> +<li> +<p>频率是1000HZ周期是1/1000 s</p> +</li> +<li> +<p>所以节拍是1ms</p> +</li> +<li> +<p>#define RT_ <em>TiCK</em> PER_ SECOND 1000</p> +</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d00c117cba6245909ad5fdab19c9bf74.png" +loading="lazy" +></p> +<h4 id="1void-systick_handler">1、void SysTick_Handler() +</h4><p>在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行<code>void SysTick_Handler</code>(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)</p> +<p><img src="https://img-blog.csdnimg.cn/c97f508be8c844a7bfa08cff57233dc1.png" +loading="lazy" +></p> +<blockquote> +<p>可以发现在<code>void SysTick_Handler()</code>这个函数中,首先会执行中断入口函数,然后<code>void rt_tick_increase</code>对<code>rt_tick</code>(系统滴答时钟,初值为0,静态<code>全局变量</code>)进行自加操作,会记录从启动到现在的时钟节拍数</p> +</blockquote> +<h4 id="2void-rt_tick_increase">2、void rt_tick_increase() +</h4><p><img src="https://img-blog.csdnimg.cn/b7122a14e60444e29f36e106bfb5166d.png" +loading="lazy" +></p> +<p><code>也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断 </code></p> +<h4 id="3rt_tick_getvoid">3、rt_tick_get(void); +</h4><p>名称:获取系统统计函数</p> +<p>功能:返回当前操作系统的时钟数</p> +<p>返回值:返回当前时钟数</p> +<p><img src="https://img-blog.csdnimg.cn/dd9e18ad7b4942ce9af13f1870fcc232.png" +loading="lazy" +></p> +<h2 id="二定时器管理">二、定时器管理 +</h2><h4 id="1概念">1、概念 +</h4><p>定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有<code>硬件定时器</code>和<code>软件定时器</code>之分:</p> +<p>1)<strong>硬件定时器</strong>是芯片本身提供的定时功能。<code>一般是由外部晶振(HSE)提供给芯片输入时钟</code>,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是<code>中断触发方式</code>。</p> +<p>2)<strong>软件定时器</strong>是由<code>操作系统提供的一类系统接口</code>,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。</p> +<p>RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即<code>定时数值必须是 OS Tick 的整数倍</code>,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。</p> +<h4 id="2rt-thread定时器介绍">2、RT-Thread定时器介绍 +</h4><p>RT-Thread 的定时器提供两类定时器机制:</p> +<p>第一类是<code>单次触发</code>定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 +第二类是<code>周期触发</code>定时器,这类定时器会周期性的触发定时器事件,直到<code>用户手动的停止</code>,否则将永远持续执行下去。</p> +<p>另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 <code>HARD_TIMER </code>模式(硬件定时器模式)与<code> SOFT_TIMER</code> 模式(软件定时器模式),如下图。</p> +<p><img src="https://img-blog.csdnimg.cn/36887975b53c4dc684343c70a2f8db09.png" +loading="lazy" +></p> +<p>1)HARD_TIMER 模式:中断上下文</p> +<p>HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数<code>RT_TIMER_FLAG_HARD_TIMER</code>来指定。</p> +<p>在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:<code>执行时间应该尽量短,执行时不应导致当前上下文挂起、等待</code>。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。</p> +<p>2)SOFT_TIMER 模式:线程上下文</p> +<p>SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。</p> +<p>该模式被启用后,系统会在<code>初始化时创建一个 timer 线程</code>,然后 <code>SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行</code>。可以在初始化 / 创建定时器时使用参数 <code>RT_TIMER_FLAG_SOFT_TIMER </code>来指定设置 <code>SOFT_TIMER</code> 模式。</p> +<h4 id="3定时器源码分析">3、定时器源码分析 +</h4><p>1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/0ee79523a62540a7a18155a0d9010365.png" +loading="lazy" +></p> +<p>2)rt_system_timer_init(硬件定时器初始化)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_system_timer_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span><span class="c1">// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_list_init</span><span class="p">(</span><span class="n">rt_timer_list</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)rt_system_timer_thread_init(软件定时器初始化)</p> +<p><img src="https://img-blog.csdnimg.cn/68e5d39a7cf94149a474f05b0f370717.png" +loading="lazy" +></p> +<h4 id="4定时器工作机制">4、定时器工作机制 +</h4><p>下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的<code>全局变量</code>:</p> +<p>(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);</p> +<p>(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照<code>以超时时间排序</code>的方式<code>插入到 rt_timer_list 链表</code>中。</p> +<p>如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。</p> +<p><img src="https://img-blog.csdnimg.cn/bb6521cccf884694867fd32a5c76da27.png" +loading="lazy" +></p> +<p>而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),<code>50 个 tick 以后,rt_tick 从 20 增长到 70</code>,与 <code>Timer1 的 timeout 值相等</code>,这时会<code>触发与 Timer1 定时器相关联的超时函数</code>,同时将 <code>Timer1 从 rt_timer_list 链表上删除</code>。</p> +<p>同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。</p> +<p>如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 <code>timeout=rt_tick+300=330</code>, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:</p> +<p><img src="https://img-blog.csdnimg.cn/515005f47d5148848a7ea4fe883b6f39.png" +loading="lazy" +></p> +<h4 id="5定时器相关接口">5、定时器相关接口 +</h4><p>1)<strong>动态创建定时器</strong></p> +<p>动态创建声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>详细函数定义:</p> +<p><img src="https://img-blog.csdnimg.cn/87411b4f65564541a22792b8fc676ec1.png" +loading="lazy" +></p> +<p>查看flag定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_ONE_SHOT 0x0 </span><span class="c1">// 单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_PERIODIC 0x2 </span><span class="c1">// 周期性触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_HARD_TIMER 0x0 </span><span class="c1">// 硬件定时器模式 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_SOFT_TIMER 0x4 </span><span class="c1">// 软件定时器模式 +</span></span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>同时这里我们注意到<code>rt_timer_create</code>这个函数的返回值是<code>rt_timer_t</code>,通过查找定义可以发现该类型是通过typedef重命名的</p> +<p>也就是说<code>struct rt_timer</code> &lt;=&gt;<code>*rt_timer_t</code></p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">rt_timer</span> <span class="o">*</span><span class="kt">rt_timer_t</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; inherit from rt_object */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_list_t</span> <span class="n">row</span><span class="p">[</span><span class="n">RT_TIMER_SKIP_LIST_LEVEL</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout_func</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">);</span> <span class="cm">/**&lt; timeout function */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">;</span> <span class="cm">/**&lt; timeout function&#39;s parameter */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">init_tick</span><span class="p">;</span> <span class="cm">/**&lt; timer timeout tick */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout_tick</span><span class="p">;</span> <span class="cm">/**&lt; timeout tick */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2)<strong>删除定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_timer_delete(rt_timer_t timer); +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:返回操作系统的状态,成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/71ccf0b21d70422fa817b7f9ae7d6843.png" +loading="lazy" +></p> +<p>3)<strong>动态创建定时器演示</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义 )。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写中断回调函数(超时函数) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 返回值结构图定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>4)<strong>开启定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/3542f82f0cc84f4f9c74b871c17753fe.png" +loading="lazy" +></p> +<p>5)实例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在超时函数中编写代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息</p> +<p>6)<strong>静态创建定时器</strong></p> +<p>函数定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们看下<code>rt_timer_init</code>这个函数的返回值和参数</p> +<p>返回值:void</p> +<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">timer</td> +<td style="text-align:center">结构体指针类型</td> +</tr> +<tr> +<td style="text-align:center">name</td> +<td style="text-align:center">名字</td> +</tr> +<tr> +<td style="text-align:center">timeout</td> +<td style="text-align:center">超时回调函数指针</td> +</tr> +<tr> +<td style="text-align:center">parameter</td> +<td style="text-align:center">传递给超时回调函数的参数</td> +</tr> +<tr> +<td style="text-align:center">time</td> +<td style="text-align:center">定时器时间</td> +</tr> +<tr> +<td style="text-align:center">flag</td> +<td style="text-align:center">定时器标志</td> +</tr> +</tbody> +</table> +<p>7)<strong>脱离函数</strong>(静态创建时使用)</p> +<p>描述:当<code>静态创建</code>的定时器不需要在使用时,我们调用下面这个函数接口</p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_detach</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>返回值:成功返回0,失败返回1</p> +<p>8)<strong>定时器控制</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> <span class="kt">int</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>cmd命令定义查看</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_TIME 0x0 </span><span class="cm">/**&lt; set timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_TIME 0x1 </span><span class="cm">/**&lt; get timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_ONESHOT 0x2 </span><span class="cm">/**&lt; change timer to one shot */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_PERIODIC 0x3 </span><span class="cm">/**&lt; change timer to periodic */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_STATE 0x4 </span><span class="cm">/**&lt; get timer run state active or deactive*/</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cb30a12c60e24f51a5ef081c296347bd.png" +loading="lazy" +></p> +<p>实例:</p> +<blockquote> +<p>查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/67007c956ebd48478e44b9233abd8efe.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> <span class="n">tm2</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm2_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">10</span><span class="p">)</span><span class="c1">// 当flags标志位位10时,设置单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_ONESHOT</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_TIME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">timeout</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[%u]tm2_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="nf">rt_tick_get</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 动态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 静态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span><span class="s">&#34;tm2_demo&#34;</span><span class="p">,</span><span class="n">tm2_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="三高精度延时">三、高精度延时 +</h2><blockquote> +<p><code>注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间</code></p> +</blockquote> +<ul> +<li>函数声明:<code>void rt_hw_us_delay(rt_uint32_t us);</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/43a92b7bdd884f18bf6ce522214cb520.png" +loading="lazy" +></p> +<ul> +<li>应用场景:应用于某些场景下对高精度延时有要求的情况下</li> +</ul>env工具学习https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post env工具学习" /><h4 id="一基础配置">一、基础配置 +</h4><p>1.首先需要下载git并配置好相应的环境变量</p> +<p>2.双击env,在setting中设置</p> +<p><img src="https://img-blog.csdnimg.cn/709a490d50c24945a2b06409d51b3209.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这样就可以指定文件夹打开env工具了</p> +<h4 id="二基本命令学习">二、基本命令学习 +</h4><p>1.scons:编译</p> +<p><img src="https://img-blog.csdnimg.cn/976aba29a258481d9128f4b984f78139.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]" +></p> +<p><code>(1)scons:</code>编译并打印相关内部信息 +<code>(2)scons -c:</code>清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +<code>(3)scons -s:</code>编译而不打印具体的内部命令 +<code>(4)scons --target=XXX:</code>使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=iar +</span></span><span class="line"><span class="cl">scons --target=mdk4 +</span></span><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(5)scons -jN:</code>多线程编译目标,在多核计算机上可以使用此命令加快编译速度</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons -j4 //双核编译工程 +</span></span></code></pre></td></tr></table> +</div> +</div><p><!-- raw HTML omitted -->注意:一般不建议使用,容易将编译信息和错误混杂<!-- raw HTML omitted --> +<code>(6)scons --dist:</code>搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set RTT_CC=keil +</span></span><span class="line"><span class="cl">set RTT_EXEC_PATH=C:/Keilv5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.menuconfig +打开菜单配置界面,可用户自定义模块</p> +<p>4.scons进阶学习 +scons内置函数</p> +<ul> +<li> +<p>GetCurrentDir(): +获取当前路径。</p> +</li> +<li> +<p>Glob(&rsquo;*.c&rsquo;): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。</p> +</li> +<li> +<p>GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。</p> +</li> +<li> +<p>Split(str): +将字符串 str 分割成一个列表 list。</p> +</li> +<li> +<p>DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +<code>DefineGroup()</code> 函数的参数描述:</p> +</li> +</ul> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th style="text-align:center"><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td style="text-align:center">Group 的名字</td> +</tr> +<tr> +<td>src</td> +<td style="text-align:center">Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件</td> +</tr> +<tr> +<td>depend</td> +<td style="text-align:center">Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现</td> +</tr> +<tr> +<td>parameters</td> +<td style="text-align:center">配置其他参数,可取值见下表,实际使用时不需要配置所有参数</td> +</tr> +</tbody> +</table> +<p>parameters可加入的参数:</p> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>dirs</td> +<td>SConscript 文件路径</td> +</tr> +<tr> +<td>variant_dir</td> +<td>指定生成的目标文件的存放路径</td> +</tr> +<tr> +<td>duiplicate</td> +<td>设定是否拷贝或链接源文件到 variant_dir</td> +</tr> +</tbody> +</table>Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/Tue, 12 Apr 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/cover.jpg" alt="Featured image of post Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)" /><h2 id="1microsoft-visual-c-140安装">1、Microsoft Visual C++ 14.0安装 +</h2><p>这里附上百度网盘下载链接: +链接: <a class="link" href="https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88</a> 提取码: ec88</p> +<p>下载完成后双击打开 +<img src="https://img-blog.csdnimg.cn/04150c3c158c4baab13f0646ab6bb578.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>默认下载方式即可</p> +<hr> +<h2 id="2pycocotools20版本安装">2、Pycocotools2.0版本安装 +</h2><h4 id="1准备材料">(1)准备材料: +</h4><ul> +<li><a class="link" href="https://github.com/cocodataset/cocoapi" target="_blank" rel="noopener" +>下载pycocotools安装包</a>(可直接git拉取到本地文件夹)</li> +</ul> +<h4 id="2源码配置">(2)源码配置 +</h4><p>打开下载好的pycocotools,双击打开<code>setup.py</code>(文件路径:\cocoapi\PythonAPI\setup.py)</p> +<p><img src="https://img-blog.csdnimg.cn/985a37a42b1043bc9dc87d3c3e4e1d0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这里<code>将蓝色部分删除,只保留红色部分</code>(切记需要执行这一步!!!)</p> +<p>开始界面找到所有应用并打开<code>Anaconda Powershell Prompt</code></p> +<p><img src="https://img-blog.csdnimg.cn/9ad6e210127c49c9bfb16f9fd9b65968.png" +loading="lazy" +></p> +<p>先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。</p> +<p>如上图所示进入到<code>\cocoapi\PythonAPI</code>该目录下</p> +<p>分别执行以下两个命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="o">--</span><span class="n">inplace</span> +</span></span><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="n">install</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/02ec23e44b3848609cc74c8c28368a0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>执行pip list查看</p> +<p><img src="https://img-blog.csdnimg.cn/642adca979d64daba7f8d2164e88443c.png" +loading="lazy" +> +此时回到<code>\cocoapi\PythonAPI</code>目录下,可以看到生成了相关文件 +<img src="https://img-blog.csdnimg.cn/bdde5563cb794cf1962800f4656b71f5.png" +loading="lazy" +alt="在这里插入图片描述" +> +将<code>pycocotools</code>和<code>pycocotools.egg-info</code>文件夹复制到你所创建的虚拟环境中(位置:Anaconda3-&gt;envs-&gt;python_env-&gt;Lib-&gt;site-packages) +<img src="https://img-blog.csdnimg.cn/8dd05ee9c4724de4a2ba536ad84aec81.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>至此所有问题解决!</p>总结:开发板挂载根文件系统遇到的一些问题https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/Wed, 30 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/cover.jpg" alt="Featured image of post 总结:开发板挂载根文件系统遇到的一些问题" /><h2 id="一桥接网络">一、桥接网络 +</h2><h4 id="1简介">1、简介 +</h4><p>是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址</p> +<h4 id="注意避坑">注意避坑: +</h4><p>如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。</p> +<h4 id="2解决办法">2、解决办法: +</h4><p>&lt;1&gt;选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241318456.png" +loading="lazy" +alt="image-20230424131854375" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241319850.png" +loading="lazy" +alt="image-20230424131957782" +></p> +<p>&lt;2&gt;无线网卡连接</p> +<p>考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)</p> +<p>如下配置:</p> +<ul> +<li>主机配置</li> +</ul> +<p>首先电脑win+R,输入<code>cmd</code>进入终端,然后输入命令:<code>ipconfig</code>,找到自己的热点网络信息</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320409.png" +loading="lazy" +alt="image-20230424132028276" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320692.png" +loading="lazy" +alt="image-20230424132041431" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241321679.png" +loading="lazy" +alt="image-20230424132117501" +></p> +<ul> +<li>虚拟机配置</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322849.png" +loading="lazy" +alt="image-20230424132214739" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322385.png" +loading="lazy" +alt="image-20230424132233318" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322519.png" +loading="lazy" +alt="image-20230424132250210" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">保存退出后,再次输入命令: +</span></span><span class="line"><span class="cl">首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡) +</span></span><span class="line"><span class="cl">然后启用网卡:ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="二开发板端测试">二、开发板端测试: +</h2><p><code>以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客</code></p> +<p><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124407302?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【Linux系统开发】x210开发板根目录文件系统构建</a></p> +<p>我们打开secureCRT:</p> +<p>开机先ping下虚拟机网络:<code>ping '虚拟机IP'</code></p> +<blockquote> +<p>注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="err">方法一:打开命令:</span><span class="n">sudo</span> <span class="n">gedit</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">NetworkManager</span><span class="o">/</span><span class="n">nm</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">settings</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">出现文件内容:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># This file is installed into /etc/NetworkManager, and is loaded by</span> +</span></span><span class="line"><span class="cl"><span class="c1"># NetworkManager by default. To override, specify: &#39;--config file&#39;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># during NM startup. This can be done by appending to DAEMON_OPTS in</span> +</span></span><span class="line"><span class="cl"><span class="c1"># the file:</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"><span class="c1"># /etc/default/NetworkManager</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">main</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">plugins</span><span class="o">=</span><span class="n">ifupdown</span><span class="p">,</span><span class="n">keyfile</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">ifupdown</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">managed</span><span class="o">=</span><span class="bp">true</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">(这里</span><span class="n">false改成true</span><span class="err">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">方法二:虚拟机重置网卡 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ifdown eth0 +</span></span><span class="line"><span class="cl">ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>当开发板ping通虚拟机后,我们在secureCRT控制台输入<code>reset</code>命令重启开发板</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323671.png" +loading="lazy" +alt="image-20230424132308595" +></p> +<p>这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323776.png" +loading="lazy" +alt="image-20230424132323723" +></p> +<p>解决:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mount -t nfs -o nolock &#39;开发板ipaddr ip&#39;:/root/rootfs/x210_rootfs //再次重新挂载根文件系统 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//NFC网络重启 +</span></span><span class="line"><span class="cl">/etc/init.d/nfs-kernel-server restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323050.png" +loading="lazy" +alt="image-20230424132335917" +></p> +<p>问题解决!</p>多线程技术学习(基于Linux)https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post 多线程技术学习(基于Linux)" /><h2 id="1linux多线程概念">1.Linux多线程概念 +</h2><blockquote> +<p><strong>(1)线程:指运行中的程序的调度单位。</strong></p> +</blockquote> +<blockquote> +<p><strong>(2)多线程的优点:</strong></p> +</blockquote> +<ul> +<li>运行与一个线程中的多个线程,他们彼此之间使用<strong>相同的地址空间</strong>,<strong>共享大部分数据</strong>,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。</li> +<li>进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式</li> +<li>应用程序响应速度提高</li> +<li>使多CPU系统更加高效</li> +<li>改善程序结构</li> +</ul> +<blockquote> +<p><strong>(3)线程的生命周期</strong></p> +</blockquote> +<p>就绪-&gt;运行-&gt;阻塞-&gt;终止</p> +<hr> +<h2 id="2linux线程实现">2.linux线程实现 +</h2><blockquote> +<p><strong>(1)线程创建</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含 +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) +</code></pre> +</li> +<li> +<p>函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数 <br> +arg: start_rtn的参数</p> +</li> +</ul> +<blockquote> +<p><strong>(2)线程退出</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +void pthread_exit(void * rval_ptr)</li> +<li>功能:终止调用线程Rval_ptr:线程退出返回值的指针。</li> +</ul> +<blockquote> +<p><strong>(3)线程等待</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_join(pthread_t tid,void **rval_ptr) +</code></pre> +</li> +<li> +<p>功能:阻塞调用线程,直到指定的线程终止。</p> +</li> +<li> +<p>函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针</p> +</li> +</ul> +<blockquote> +<p><strong>(4)线程标识获取</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +pthread_t pthread_self(void)</li> +<li>功能:获取调用线程的 thread identifier</li> +</ul> +<blockquote> +<p><strong>(5)线程清除</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> void pthread_cleanup_push(void (*rtn)(void *),void *arg) +</code></pre> +</li> +<li> +<p>功能:将清除函数压入清除栈</p> +</li> +<li> +<p>函数说明: +Rtn:清除函数 +Arg:清除函数的参数</p> +</li> +</ul> +<hr> +<h2 id="3线程同步的方法">3.线程同步的方法 +</h2><p>进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:</p> +<blockquote> +<p>互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions</p> +</blockquote> +<hr> +<h2 id="4线程的互斥">4.线程的互斥 +</h2><p>线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。</p> +<blockquote> +<p><strong>(1)创建</strong></p> +</blockquote> +<p>在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:</p> +<ul> +<li>对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER</li> +<li>对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。</li> +</ul> +<blockquote> +<p>函数使用: +头文件: +#include &lt;pthread.h&gt;</p> +</blockquote> +<pre><code>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) +int pthread_mutex_destroy(pthread_mutex_t *mutex) +</code></pre> +<blockquote> +<p><strong>(2)加锁</strong></p> +</blockquote> +<p>对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。</p> +<blockquote> +<p>函数使用:</p> +</blockquote> +<pre><code>int pthread_mutex_lock(pthread_mutex_t *mutex) +int pthread_mutex_trylock(pthread_mutex_t *mutex) +</code></pre> +<p>返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。</p> +<blockquote> +<p><strong>(3)解锁</strong></p> +</blockquote> +<p>在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。</p> +<pre><code>int pthread_mutex_unlock(pthread_mutex_t *mutex) +</code></pre> +<hr> +<h2 id="5互斥pk信号量">5.互斥PK信号量 +</h2><blockquote> +<p>Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:</p> +<ol> +<li>mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放</li> +<li>初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。</li> +</ol> +</blockquote> +<hr> +<h2 id="6信号量操作代码演示">6.信号量操作(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;semaphore.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">sem_t sem; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sem_wait(&amp;sem); // 接收信号量 +</span></span><span class="line"><span class="cl"> /* +</span></span><span class="line"><span class="cl"> Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 +</span></span><span class="line"><span class="cl"> 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> //while(strncmp(buf,&#34;end&#34;,3) != 0) +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> sem_init(&amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(scanf(&#34;%s&#34;,buf)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> sem_post(&amp;sem); //增加(解锁)sem指向的信号量 +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="7互斥操作函数演示">7.互斥操作(函数演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">pthread_mutex_t mutex; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sleep(1); +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 互斥加锁 +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 解锁 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_mutex_init(&amp;mutex,NULL); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 对互斥对象加锁锁定 +</span></span><span class="line"><span class="cl"> scanf(&#34;%s&#34;,buf); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 输入后解锁 +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> pthread_mutex_destroy(&amp;mutex); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="8条件变量代码演示">8.条件变量(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1">#include&lt;stdio.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;string.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;pthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;stdlib.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">子线程处理</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_cond_t</span> <span class="n">cond</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">flag</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="o">*</span><span class="k">func</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">flag</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span><span class="o">//</span> <span class="err">互斥加锁</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span><span class="o">//</span> <span class="err">线程同步等待</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> <span class="o">//</span> <span class="err">解锁</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_exit</span><span class="p">(</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_t</span> <span class="n">th</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="err">初始化条件变量</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">,</span><span class="k">func</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_create</span><span class="p">()</span><span class="err">函数在调用进程中启动一个新线程</span><span class="p">,</span><span class="err">创建成功返回</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_create error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;please input string,end with Enter.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">scanf</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">发送信号</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="s2">&#34;end&#34;</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;process end</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char .</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;wait reclaim child thread.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">函数等待由</span><span class="n">thread指定的线程结束</span><span class="err">。如果该线程已经终止,则</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">立即返回。</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_join error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;reclaim child thread successfully.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">条件变量销毁</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>信号量及PV操作详解https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/Thu, 10 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 信号量及PV操作详解" /><h2 id="信号量">信号量 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->一个特殊变量</li> +<li><!-- raw HTML omitted -->用于进程间传递信息的一个整数值</li> +</ul> +</blockquote> +<p>定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct semaphore +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int count; +</span></span><span class="line"><span class="cl"> quenue Type quenue; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<ul> +<li><!-- raw HTML omitted -->信号量说明:semaphore s;</li> +<li><!-- raw HTML omitted -->对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen))</li> +</ul> +</blockquote> +<h2 id="pv操作定义">P、V操作定义 +</h2><p><!-- raw HTML omitted -->P(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.count --; //信号量值减一 +</span></span><span class="line"><span class="cl"> if(s.count&lt;0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 该进程状态置为阻塞态; +</span></span><span class="line"><span class="cl"> 将该进程插入相应的等待队列s.quenue末尾; +</span></span><span class="line"><span class="cl"> 重新调度 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>down</code>,<code>semwait</code>:也代表P操作</p> +<p><!-- raw HTML omitted -->V(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.ount++; +</span></span><span class="line"><span class="cl"> if(s.count&lt;=0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 唤醒相应等待队列s.queue中等待的一个进程; +</span></span><span class="line"><span class="cl"> 改变其状态为就绪态,并将其插入就绪队列; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>up</code>,<code>semsignal</code>:也代表V操作</p> +<blockquote> +<p>相关说明</p> +<ul> +<li><!-- raw HTML omitted -->P,V操作为原语操作</li> +<li><!-- raw HTML omitted -->在信号量上定义了三个操作 +<!-- raw HTML omitted -->初始化(非负数)、P操作、V操作<!-- raw HTML omitted --></li> +<li><!-- raw HTML omitted -->最初提出的是二元信号量(解决互斥) +之后,推广到一般信号量(多值)或技术信号量(解决同步)</li> +</ul> +</blockquote> +<h2 id="用pv操作解决进程间互斥问题">用PV操作解决进程间互斥问题 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->分析并发进程的关键活动,划定临界区</li> +<li><!-- raw HTML omitted -->设置信号量mutux,初值为1</li> +<li><!-- raw HTML omitted -->在临界区前实施P(mutux)</li> +<li><!-- raw HTML omitted -->在临界区之后实施V(mutux)</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/9f7d7a26cf6a41048d7205423383fa64.png" +loading="lazy" +alt="图片演示" +></p> +<blockquote> +<p>相关解释:</p> +</blockquote> +<ul> +<li> +<p><code>临界区</code> : 我们把并发进程中与共享变量有关的程序段称为临界区。</p> +</li> +<li> +<p><code>信号量</code> : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。</p> +</li> +<li> +<p><code>进程的互斥</code>:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。</p> +</li> +<li> +<p><code>进程的同步</code>:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。</p> +</li> +<li> +<p><code>pv操作又称wait,signal原语。</code> +主要是操作进程中对进程控制的信息量的加减控制。</p> +</li> +</ul> +<blockquote> +<p><!-- raw HTML omitted --><code>注意:</code>在霍尔管程中,<code>wait操作</code>和<code>signal操作</code>用于被设计为两个可以中断的过程,而非<code>原语。</code> +<!-- raw HTML omitted -->在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 +条件变量的两种操作:</p> +<ul> +<li>wait()操作<!-- raw HTML omitted -->[阻塞调用进程]<!-- raw HTML omitted --></li> +<li>signal()操作<!-- raw HTML omitted -->[释放/唤醒在条件变量上阻塞的进程]<!-- raw HTML omitted --></li> +</ul> +</blockquote> +<ul> +<li>wait用法: +wait(num),num是目标参数,wait的作用是使其(信息量)减一。 +如果信息量&gt;=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 +signal用法: +signal(num),num是目标参数,signal的作用是使其(信息量)加一。 +如果信息量&gt;0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。</li> +</ul> +<blockquote> +<p>本文资源来自<a class="link" href="https://www.coursera.org/learn/os-pku" target="_blank" rel="noopener" +>Operating Systems</a> +参考:<a class="link" href="https://blog.csdn.net/thebestway/article/details/105034840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164992015416780255296134%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=164992015416780255296134&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-105034840.142%5ev8%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=wait%E5%92%8Csignal%E5%8E%9F%E8%AF%AD&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>操作系统P,V(wait,signal原语)操作讲解</a></p> +</blockquote>进程上下文和线程上下文https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/Tue, 08 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/cover.jpg" alt="Featured image of post 进程上下文和线程上下文" /><h2 id="进程">进程 +</h2><p><code>操作系统资源分配的基本单位</code>,也就是指计算机中已执行的程序。</p> +<ul> +<li>在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,<code>进程</code>是程序的基本执行实体;</li> +<li>在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是<code>线程</code>的容器。</li> +<li>程序本身只是指令、数据及其组织形式的描述,相当于一个名词,<code>进程</code>才是程序(那些指令和数据)的真正<code>执行实例</code>.</li> +</ul> +<h2 id="进程上下文">进程上下文 +</h2><p><code>进程上下文</code>就是表示<code>进程信息</code>的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。</p> +<p>拿<code>Linux进程</code>举例: +&mdash;-进程的运行环境主要包括:</p> +<blockquote> +<p>1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 +2.环境变量:提供进程运行所需的环境信息。 +3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 +4.进程访问设备或者文件时的权限。 +5.各种硬件寄存器。 +6.地址转换信息。</p> +</blockquote> +<p>由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。</p> +<h2 id="线程">线程 +</h2><p><code>操作系统能够进行运算调度的最小单位</code>。</p> +<ul> +<li>大部分情况下,它被包含在进程之中,是进程中的实际运作单位。</li> +<li>一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。</li> +<li>线程是独立调度和分派的基本单位。 +线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。</li> +<li>同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。</li> +</ul> +<h2 id="线程上下文">线程上下文 +</h2><p>进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。<code>同样的,线程也有上下文。</code></p> +<blockquote> +<p>当线程被抢占时,就会发生线程之间的上下文切换。 +如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。</p> +</blockquote> +<p>线程上下文与进程上下文对比</p> +<table> +<thead> +<tr> +<th>上下文内容</th> +<th>进程</th> +<th>线程</th> +</tr> +</thead> +<tbody> +<tr> +<td>指向可执行文件的指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>栈</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>内存(数据段和堆)</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>状态</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>优先级</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>程序IO的状态</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>授予权限</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>调度信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>审计信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件描述符</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件读/写指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>寄存器组</td> +<td>×</td> +<td>×</td> +</tr> +</tbody> +</table>Archiveshttps://kurisaw.github.io/archives/Sun, 06 Mar 2022 00:00:00 +0000https://kurisaw.github.io/archives/Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p>Abouthttps://kurisaw.github.io/about/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/about/<h2 id="hi-there">Hi there!👋 +</h2><p>I&rsquo;m KurisaW,or you can call me yifang.</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="l">🔭 Now I am a junior student ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">🌱 I’m currently learning RT-Thread、linux、ROS ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">👯 I’m looking to collaborate on Embedded or neural network ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">🤔 I&#39;m looking forward to sharing my experience and learning to help some beginners get through the rookie phase faster ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">💬 Ask me about Linux、Embedded ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">😊 I will be happy to discuss technology and knowledge with you and look forward to your visit!</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>Contact me:</code></p> +<ul> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> +<p><code>You can also choose to get in touch with me by adding wechat!</code></p> +<p><img src="https://user-images.githubusercontent.com/98592772/218299666-0cb3baea-a528-4216-99bd-06806149aaa9.png" +loading="lazy" +alt="Wechat" +></p>Documentshttps://kurisaw.github.io/documents/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/documents/<h1 id="说明">说明 +</h1><p>这里我存放了一些个人搜集的文档资源,支持PDF在线查看,同时也欢迎各位在评论区留下相关资源链接!</p> +<p>由于构建方式使用的是PDF.js插件,是为html5实现的在线预览pdf框架,所以使用的前提是浏览器要支持html5。该插件不需要任何本地支持,对浏览器的兼容性也比较好(低版本的IE浏览器不支持)。</p> +<p>配置仓库入口:<a class="link" href="https://github.com/kurisaW/Npdf" target="_blank" rel="noopener" +>https://github.com/kurisaW/Npdf</a></p> +<p><strong>注:目前本博客的pdf资源已部分上传至infinityfree服务器,较之pdf.js有更快响应速度,后续考虑国内CDN加速,当然想要学习和了解pdf.js的构建方式也可参考此仓库<a class="link" href="https://github.com/kurisaW/Npdf" target="_blank" rel="noopener" +>Npdf</a>;由于部分pdf文件较大,反应速度慢属于正常现象。</strong></p> +<h1 id="目前上传的pdf资源如下">目前上传的PDF资源如下: +</h1><h3 id="精品专栏">精品专栏 +</h3><ul> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/05/30%e5%a4%a9%e8%87%aa%e5%88%b6%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f-%e5%9b%be%e7%81%b5%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b8%9b%e4%b9%a6.pdf" target="_blank" rel="noopener" +>30天自制操作系统-图灵程序设计丛书</a></li> +</ul> +<h3 id="c语言专栏">C语言专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=GCC.chinese-manual.pdf" target="_blank" rel="noopener" +>GCC.chinese-manual.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e9%99%b7%e9%98%b1%e4%b8%8e%e7%bc%ba%e9%99%b7.pdf" target="_blank" rel="noopener" +>C陷阱与缺陷.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e9%9b%86%ef%bc%88%e9%97%ae%e9%a2%98%e6%8f%90%e9%ab%98%e7%89%88%ef%bc%89.pdf" target="_blank" rel="noopener" +>C语言常见问题集(问题提高版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e5%87%bd%e6%95%b0%e5%a4%a7%e5%85%a8.pdf" target="_blank" rel="noopener" +>C语言函数大全.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e6%b7%b1%e5%ba%a6%e8%a7%a3%e5%89%96-%e8%a7%a3%e5%bc%80%e7%a8%8b%e5%ba%8f%e5%91%98%e9%9d%a2%e8%af%95%e7%ac%94%e8%af%95%e7%9a%84%e7%a7%98%e5%af%86.pdf" target="_blank" rel="noopener" +>C语言深度解剖-解开程序员面试笔试的秘密.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e6%8c%87%e9%92%88%e7%bb%8f%e9%aa%8c%e6%80%bb%e7%bb%93.pdf" target="_blank" rel="noopener" +>C语言指针经验总结.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/C%e8%af%ad%e8%a8%80%e8%a7%84%e8%8c%83%e6%a0%87%e5%87%86-C99.pdf" target="_blank" rel="noopener" +>C语言规范标准-C99.pdf</a></li> +</ul> +<h3 id="c专栏">C++专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%bb%8e%e6%94%be%e5%bc%83C%e8%af%ad%e8%a8%80%e5%88%b0%e4%bd%bf%e7%94%a8CPlusPlus%e5%88%b7%e7%ae%97%e6%b3%95%e7%9a%84%e7%ae%80%e6%98%8e%e6%95%99%e7%a8%8b.pdf" target="_blank" rel="noopener" +>从放弃C语言到使用CPlusPlus刷算法的简明教程.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Google.CPlusPlus-Style-Guide.pdf" target="_blank" rel="noopener" +>Google.CPlusPlus-Style-Guide.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e7%bc%96%e7%a8%8b%e8%a7%84%e8%8c%83-101%e6%9d%a1%e8%a7%84%e5%88%99%e5%87%86%e5%88%99%e4%b8%8e%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5.pdf" target="_blank" rel="noopener" +>CPlusPlus编程规范-101条规则准则与最佳实践.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e6%a0%87%e5%87%86%e7%a8%8b%e5%ba%8f%e5%ba%93.pdf" target="_blank" rel="noopener" +>CPlusPlus标准程序库.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e5%af%b9%e8%b1%a1%e6%a8%a1%e5%9e%8b.pdf" target="_blank" rel="noopener" +>CPlusPlus对象模型.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Effective_STL%e4%b8%ad%e6%96%87%e7%89%88.pdf" target="_blank" rel="noopener" +>Effective_STL中文版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=STL%e6%ba%90%e7%a0%81%e5%89%96%e6%9e%90.pdf" target="_blank" rel="noopener" +>STL源码剖析.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%b7%9f%e6%88%91%e4%b8%80%e8%b5%b7%e5%86%99makefile.pdf" target="_blank" rel="noopener" +>跟我一起写makefile.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%ba%a6%e6%8e%a2%e7%b4%a2CPlusPlus%e5%af%b9%e8%b1%a1%e6%a8%a1%e5%9e%8b.pdf" target="_blank" rel="noopener" +>深度探索CPlusPlus对象模型.pdf</a></li> +</ul> +<h3 id="linux专栏">Linux专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux-series-summary-manual.pdf" target="_blank" rel="noopener" +>Linux-series-summary-manual.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux_UNIX%e7%b3%bb%e7%bb%9f%e7%bc%96%e7%a8%8b%e6%89%8b%e5%86%8c%ef%bc%88%e4%b8%8a%ef%bc%89.pdf" target="_blank" rel="noopener" +>Linux_UNIX系统编程手册(上).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux_UNIX%e7%b3%bb%e7%bb%9f%e7%bc%96%e7%a8%8b%e6%89%8b%e5%86%8c%ef%bc%88%e4%b8%8b%ef%bc%89.pdf" target="_blank" rel="noopener" +>Linux_UNIX系统编程手册(下).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux%e5%86%85%e6%a0%b8%e8%ae%be%e8%ae%a1%e4%b8%8e%e5%ae%9e%e7%8e%b0.pdf" target="_blank" rel="noopener" +>Linux内核设计与实现.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=linux%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4%e5%a4%a7%e5%85%a8.pdf" target="_blank" rel="noopener" +>linux常用命令大全.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=linux%e5%86%85%e6%a0%b8%e5%ae%8c%e5%85%a8%e6%b3%a8%e9%87%8a.pdf" target="_blank" rel="noopener" +>linux内核完全注释.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux%e7%b3%bb%e7%bb%9f%e5%91%bd%e4%bb%a4%e5%8f%8ashell%e8%84%9a%e6%9c%ac%e5%ae%9e%e8%b7%b5%e6%8c%87%e5%8d%97linuxunix%e6%8a%80%e6%9c%af%e4%b8%9b%e4%b9%a6.pdf" target="_blank" rel="noopener" +>Linux系统命令及shell脚本实践指南linuxunix技术丛书.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e9%b8%9f%e5%93%a5%e7%9a%84LINUX%e7%a7%81%e6%88%bf%e8%8f%9c_%e5%9f%ba%e7%a1%80%e5%ad%a6%e4%b9%a0%e7%af%87%28%e7%ac%ac%e4%b8%89%e7%89%88%29.pdf" target="_blank" rel="noopener" +>鸟哥的LINUX私房菜_基础学习篇(第三版).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e9%b8%9f%e5%93%a5%e7%9a%84Linux%e7%a7%81%e6%88%bf%e8%8f%9c%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%9e%b6%e8%ae%be%e7%af%87%28%e7%ac%ac%e4%b8%89%e7%89%88%29.pdf" target="_blank" rel="noopener" +>鸟哥的Linux私房菜服务器架设篇(第三版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%85%a5Linux%e5%86%85%e6%a0%b8%e6%9e%b6%e6%9e%84%28%e5%9b%be%e7%81%b5%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b8%9b%e4%b9%a6%c2%b7LinuxUNIX%e7%b3%bb%e5%88%97%29.pdf" target="_blank" rel="noopener" +>深入Linux内核架构(图灵程序设计丛书·LinuxUNIX系列).pdf</a></li> +</ul> +<h3 id="git专题">Git专题 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Git%e5%8f%82%e8%80%83%e6%89%8b%e5%86%8c-%e6%96%b0.pdf" target="_blank" rel="noopener" +>Git参考手册-新.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Git%e6%9d%83%e5%a8%81%e6%8c%87%e5%8d%97.pdf" target="_blank" rel="noopener" +>Git权威指南.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%bb%8e0%e5%bc%80%e5%a7%8b%e5%ad%a6%e4%b9%a0GitHub%e7%b3%bb%e5%88%97.pdf" target="_blank" rel="noopener" +>从0开始学习GitHub系列.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%b8%93%e4%b8%9agit%e4%b8%ad%e6%96%87.pdf" target="_blank" rel="noopener" +>专业git中文.pdf</a></li> +</ul> +<h3 id="笔试面试专题">笔试面试专题 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e9%9d%a2%e7%bb%8f%e6%80%bb%e7%bb%93.pdf" target="_blank" rel="noopener" +>CPlusPlus面经总结.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e7%89%9b%e5%ae%a2%e5%a4%a7%e4%bd%ac%e6%80%bb%e7%bb%93%e9%9d%a2%e8%af%95%e7%bb%8f%e9%aa%8c.pdf" target="_blank" rel="noopener" +>CPlusPlus牛客大佬总结面试经验.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e7%a8%8b%e5%ba%8f%e5%91%98%e9%9d%a2%e8%af%95%e5%ae%9d%e5%85%b8.pdf" target="_blank" rel="noopener" +>程序员面试宝典.pdf</a></li> +</ul> +<h3 id="操作系统专栏">操作系统专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e6%a6%82%e5%bf%b5.pdf" target="_blank" rel="noopener" +>操作系统概念.pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%b3%bb%e7%bb%9f%e8%a6%81%e7%b4%a0-%e4%bb%8e%e9%9b%b6%e5%bc%80%e5%a7%8b%e6%9e%84%e5%bb%ba%e7%8e%b0%e4%bb%a3%e8%ae%a1%e7%ae%97%e6%9c%ba.pdf" target="_blank" rel="noopener" +>计算机系统要素-从零开始构建现代计算机.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%b3%bb%e7%bb%9f-%e7%ac%ac3%e7%89%88.pdf" target="_blank" rel="noopener" +>深入理解计算机系统-第3版.pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%87%aa%e5%b7%b1%e5%8a%a8%e6%89%8b%e5%86%99%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f.pdf" target="_blank" rel="noopener" +>自己动手写操作系统.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=RTThread_manual.zh.pdf" target="_blank" rel="noopener" +>RTThread_manual.zh.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=RT-Thread%e7%bc%96%e7%a8%8b%e6%8c%87%e5%8d%97.pdf" target="_blank" rel="noopener" +>RT-Thread编程指南.pdf</a></li> +</ul> +<h3 id="数据结构与算法专栏">数据结构与算法专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e7%bc%96%e7%a8%8b%e4%b9%8b%e7%be%8e-%e5%ae%8c%e6%95%b4%e7%89%88.pdf" target="_blank" rel="noopener" +>编程之美-完整版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e5%89%91%e6%8c%87Offer.pdf" target="_blank" rel="noopener" +>剑指offer.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e5%89%91%e6%8c%87offer_%e5%90%8d%e4%bc%81%e9%9d%a2%e8%af%95%e5%ae%98%e7%b2%be%e8%ae%b2%e5%85%b8%e5%9e%8b%e7%bc%96%e7%a8%8b%e9%a2%98-%e7%ac%ac2%e7%89%88.pdf" target="_blank" rel="noopener" +>剑指offer_名企面试官精讲典型编程题-第2版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e4%b8%8e%e7%ae%97%e6%b3%95%e5%88%86%e6%9e%90CPlusPlus%e6%8f%8f%e8%bf%b0.pdf" target="_blank" rel="noopener" +>数据结构与算法分析CPlusPlus描述.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%b8%a5%e8%94%9a%e6%95%8f-%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e9%a2%98%e9%9b%86%28C%e8%af%ad%e8%a8%80%e7%89%88%29.pdf" target="_blank" rel="noopener" +>严蔚敏-数据结构题集(C语言版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e8%b4%aa%e5%bf%83%e7%ae%97%e6%b3%95%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」贪心算法专题精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e5%9b%9e%e6%ba%af%e7%ae%97%e6%b3%95%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」回溯算法精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e5%8a%a8%e6%80%81%e8%a7%84%e5%88%92%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」动态规划专题精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e4%ba%8c%e5%8f%89%e6%a0%91%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」二叉树专题精讲(v2.0).pdf</a></li> +</ul> +<h3 id="历年软考嵌入式系统设计师真题及答案">历年软考嵌入式系统设计师真题及答案 +</h3><ul> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e6%95%99%e7%a8%8b.pdf" target="_blank" rel="noopener" +>嵌入式系统设计师教程.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师上午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师上午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师下午试题及答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e5%8d%b7.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师上午试卷.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2009%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2009下半年嵌入式系统设计师上午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2009%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2009下半年嵌入式系统设计师下午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师上午试题及答案解析.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2011%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e4%b8%8e%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2011年下半年嵌入式系统设计师上午试题与答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2011%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2011年下半年嵌入式系统设计师下午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2012-2013%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2012-2013年下半年嵌入式系统设计师上午+下午试题及答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2014%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e5%8d%b7%e7%bb%bc%e5%90%88%e7%9f%a5%e8%af%86.pdf" target="_blank" rel="noopener" +>2014年下半年嵌入式系统设计师上午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2015%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e7%9c%9f%e9%a2%98%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2015年下半年嵌入式系统设计师上午+下午真题答案+解析.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2016%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e7%9c%9f%e9%a2%98%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2016年下半年嵌入式系统设计师上午+下午真题答案+解析.pdf</a></li> +</ul> +<h1 id="联系我">联系我 +</h1><p>如果你有相关资源想要集合到一个网站以便随时访问而又拘于时间问题没法搭建网站的话,可以与我取得联系,我将帮助你整理好资源,以此为你提供更加便利的阅读!</p> +<p>欢迎你的来访,期待与你有更好的合作!</p> +<p><a class="link" href="https://kurisaw.github.io/about/" target="_blank" rel="noopener" +>联系我请移步</a></p>Explorehttps://kurisaw.github.io/explore/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/explore/<p>If you have resources or tools that you recommend, you can contribute in the format below</p> +<p>This page&rsquo;s frontmatter:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">links</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Explore</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Here are some links to interesting and useful sites.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://kurisaw.github.io/explore/</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>image</code> field accepts both local and external images.</p>Linkshttps://kurisaw.github.io/links/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/links/<p>To use this feature, add <code>links</code> section to frontmatter.</p> +<p>This page&rsquo;s frontmatter:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">links</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">GitHub</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">GitHub is the world&#39;s largest software development platform.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.com</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">TypeScript</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://www.typescriptlang.org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">ts-logo-128.jpg</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>image</code> field accepts both local and external images.</p>Quotehttps://kurisaw.github.io/quote/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/quote/<h1 id="读书-学习-去更远的地方">📑读书 学习 去更远的地方 +</h1><hr> +<div class="video-wrapper"> +<video +controls +src="./travel.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./travel.mp4">link to the video</a> instead. +</p> +</video> +</div> +<blockquote> +<p>每个人手上都拿着一张随时可能会输的牌,在人生中寻找补救的方法。</p><span class="cite"><span>― </span><span>星野道夫, </span><a href="https://kurisaw.github.io/quote/"><cite>《在漫长的旅途中》</cite></a></span></blockquote> +<blockquote> +<p>人只有在举棋不定,无从把握的时候才感到疲惫。只有去行动就能获得解放,哪怕做的不好也比无所作为强。</p><span class="cite"><span>― </span><span>斯蒂夫·茨威格, </span><a href="https://kurisaw.github.io/quote/"><cite>《创世纪》</cite></a></span></blockquote> +<blockquote> +<p>虚心佐我闪光 谦卑助我制胜 德行辅我压迫</p><span class="cite"><span>― </span><span>阿尔贝·加缪, </span><a href="https://kurisaw.github.io/quote/"><cite>《堕落》</cite></a></span></blockquote>Searchhttps://kurisaw.github.io/search/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/search/ \ No newline at end of file diff --git a/links/index.html b/links/index.html new file mode 100644 index 000000000..362ac3bea --- /dev/null +++ b/links/index.html @@ -0,0 +1,41 @@ +Links +

Links

+

To use this feature, add links section to frontmatter.

This page’s frontmatter:

1
+2
+3
+4
+5
+6
+7
+8
+9
+
links:
+  - title: GitHub
+    description: GitHub is the world's largest software development platform.
+    website: https://github.com
+    image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
+  - title: TypeScript
+    description: TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
+    website: https://www.typescriptlang.org
+    image: ts-logo-128.jpg
+

image field accepts both local and external images.

+Licensed under CC BY-NC-SA 4.0
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover.jpg" "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover.jpg" new file mode 100644 index 000000000..1e39dfce9 Binary files /dev/null and "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover.jpg" differ diff --git "a/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_120x120_fill_q75_box_smart1.jpg" "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c55247756 Binary files /dev/null and "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_1600x0_resize_q75_box.jpg" "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9f40002cb Binary files /dev/null and "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_1600x0_resize_q75_box.jpg" differ diff --git "a/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_800x0_resize_q75_box.jpg" "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f67466ecb Binary files /dev/null and "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/cover_hub246c27766a20e08922e475827469c08_5066_800x0_resize_q75_box.jpg" differ diff --git "a/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/index.html" "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/index.html" new file mode 100644 index 000000000..02b34d4f4 --- /dev/null +++ "b/p/cplusplus-\345\237\272\347\241\200\347\237\245\350\257\206\345\244\215\344\271\240/index.html" @@ -0,0 +1,550 @@ +Cplusplus-基础知识复习 +
Featured image of post Cplusplus-基础知识复习

Cplusplus-基础知识复习

C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念

+
+

基本格式

1
+2
+3
+4
+5
+6
+7
+8
+
#include <iostream>
+using namespace std;
+
+int main(){
+	std::cout << "hello world!" << endl;
+    cout << "hello world!\n";
+    return 0;
+}
+
  • 编译预处理命令: #include <iostream>(输入输出流)
  • 命令空间 using namespace std;
  • cin >> :用于输入;cout << :用于输出; endl:用于换行
  • 源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe

特点

  • C++与C完全兼容,是C的扩展和改革
  • 支持面向对象程序设计
  • 生成的代码质量高
  • C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:抽象、封装、继承和多态

C++数据类型

主要分为三类:基本数据类型、构造数据类型、类

基本数据类型

  • 整型
  • 实型(浮点型)
  • 字符型
  • 布尔型
  • void型

构造数据类型

  • 数组类型
  • 指针类型
  • 枚举类型
  • 结构体类型
  • 共用体类型

函数重载

简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。

如:

1
+2
+
double area(double a, double b);
+double area(double r);
+
  • 注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生

类和对象*

1.类

类由说明部分和实现部分组成,其说明部分的形式如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
class 类名
+{
+private:
+    成员表1;
+    
+protected:
+    成员表2;
+    
+public:
+    成员表3;
+};
+

实现部分的形式如下:

1
+2
+3
+4
+
类名::成员函数名(形参表)
+{
+	函数体;
+}
+

注意:在类内不能对数据成员进行初始化,同时,private\protect\public三个关键字对数据成员有不同的访问控制

  • private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;
  • public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口
  • protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据

2.类的成员函数

类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:

1
+2
+3
+4
+
类型 类名::函数成员名(参数表)
+{
+	函数体
+}
+

其中::被称为作用域运算符,能指出函数成员是属于哪个类的

3.类的对象

含义

如果把类看作是数据类型,则该数据类型定义的变量就是对象

格式

在定义类之后,就可以定义对象了,一般格式为:

1
+
类名 对象名1,对象名2,...;
+

也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象

对象的使用

对于一般对象(非对象指针),访问其成员的方式为:

1
+
对象名.共有数据成员名(或共有成员函数名/参数表)
+

对于指向对象的指针,访问其成员的方式为:

1
+
对象指针名->共有数据成员名(或共有成员函数名/参数表)
+

注意:其中.为点运算符;->为箭头运算符(类似结构体)

示例

在主函数中调用Clock类中的show()函数,可写成如下形式:

1
+2
+3
+4
+5
+
Clock P, *p = &P;//定义对象P以及指向P的指针p
+
+P.show();	//调用对象P的show()函数成员
+P->show();	//调用指针P指向的show()函数成员
+(*p).show();//调用指针p指向的内容P的show()函数成员
+

类的访问权限

继承方式基类的public成员基类的protected成员基类的private成员继承引起的访问控制关系变化概括
public继承仍为public成员仍为protected成员不可见基类的非私有成员在子类的访问属性不变
protected继承变为protected成员变为protected成员不可见基类的非私有成员都为子类的保护成员
private继承变为private成员变为private成员不可见基类中的非私有成员都称为子类的私有成员

构造函数与析构函数

1.构造函数

含义

构造函数的功能是将对象初始化,其特点是与类同名,且无返回类型

格式

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
...
+public:
+	Clock(int newC,int newN,int newM);	//类中声明构造函数
+...
+
+Clock::Clock(int newC,int newN,int newM)
+{
+	c = newC;
+	n = newN;
+    m = newM;
+}
+
+int main()
+{
+	Clock p(0,0,0);	//主函数中调用构造函数来初始化对象P
+    P.show();	   //对象P调用成员函数show()来完成其他目的
+    return 0;
+}
+

2.析构函数

含义

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。

只要类的对象被销毁,就会调用该类的析构函数。

作用

析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。

示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
#include <iostream>
+using namespace std;
+
+class Line
+{
+public:
+    void setLength(double len);
+    double getLength(void);
+    Line();		//这是构造函数声明
+    ~Line();	//这是析构函数声明
+
+private:
+    double length;
+};
+
+Line::Line(void)
+{
+    cout << "object is being created" << endl;
+}
+
+Line::~Line(void)
+{
+    cout << "object is being deleted" << endl;
+}
+
+void Line::setLength(double len)
+{
+    length = len;
+}
+
+double Line::getLength(void)
+{
+    return length;
+}
+
+int main()
+{
+    Line line;
+    line.setLength(6.0);
+    cout << "length of line :" << line.getLength() << endl;
+    
+    return 0;	//main函数返回前,line对象会被自动销毁
+}
+

拷贝(复制)构造函数

含义

拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。

拷贝构造函数常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象
  • 复制对象把它作为参数传递给函数
  • 复制对象,并从函数返回这个对象

格式

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。

拷贝构造函数的常见形式如下:

1
+2
+3
+4
+
classname (const classname &obj)
+{
+    // 构造函数的主体
+}
+

拷贝构造函数的触发

在C++中,主要有以下几种情况会调用拷贝构造函数:

1.使用一个同类型对象初始化另一个对象时

1
+2
+
MyClass obj1(10); 
+MyClass obj2(obj1); // 调用拷贝构造函数
+

2.以值传递的方式将一个对象作为参数传递给函数时

1
+2
+3
+4
+5
+6
+
void myFunc(MyClass obj) {
+  // 函数接收到的obj是调用拷贝构造函数创建的
+}
+
+MyClass obj(10);
+myFunc(obj); 
+

3.返回局部对象时

1
+2
+3
+4
+
MyClass myFunc() {
+  MyClass ret(10);
+  return ret; // 调用拷贝构造函数后返回
+}
+

4.编译器优化时会让临时对象调用拷贝构造函数

1
+
MyClass(10) + MyClass(20); // 两个临时对象会调用拷贝构造函数
+

5.在容器中插入一个新元素时会调用该元素的拷贝构造函数

1
+2
+3
+
std::vector<MyClass> vec; 
+MyClass obj(10);
+vec.push_back(obj);
+

以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。

示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+
#include <iostream>
+using namespace std;
+
+class Line
+{
+public:
+    int getLength(void);
+    Line(int len);			//简单的构造函数
+    Line(const Line &obj);	 //拷贝构造函数
+    ~Line();			    //析构函数
+
+private:
+    int *ptr;
+};
+
+// 成员函数定义,包括构造函数
+Line::Line(int len)
+{
+	cout << "调用构造函数" << endl;
+    // 为指针分配内存
+    ptr = new int;
+    *ptr = len;
+}
+
+Line::Line(const Line &obj)
+{
+    cout << "调用拷贝构造函数并为指针ptr分配内存" << endl;
+    ptr = new int;
+    *ptr = *obj.ptr;	//拷贝值
+}
+
+Line::~Line(void)
+{
+    cout << "释放内存" << endl;
+    delete ptr;
+}
+
+int Line::getLength(void)
+{
+    return *ptr;
+}
+
+void display(Line obj)
+{
+    cout << "line 大小:" << endl << obj.getLength() << endl;
+}
+
+// 程序的主函数
+int main()
+{
+    Line line(10);
+    display(line);	
+    
+    return 0;
+}
+

友元函数

含义

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。

虽然友元函数的原型有在类的定义中出现过,但友元函数并不是成员函数。

友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。

格式

声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend

1
+2
+3
+4
+5
+6
+7
+8
+9
+
class Box
+{
+    double width;
+    
+public:
+    double length;
+    friend void printWidth(Box box);
+    void setWidth(double wid);
+};
+

声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:

1
+
friend class ClassTwo;
+

使用场景

C++友元函数的主要使用场景包括:

1.实现两个类之间的相互访问

如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。

2.实现运算符重载

重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。

3.模板类的访问

当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。

4.调试和测试类的实现

在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。

5.避免繁琐的getter/setter方法

友元函数可以直接访问私有数据,避免定义许多getter和setter方法。

6.状态检查

友元函数可以方便地访问对象的状态,用于调试等目的。

需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。

示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
#include <iostream>
+using namespace std;
+
+class Box
+{
+    double width;
+
+public:
+    friend void printWidth(Box box);
+    void setWidth(double wid);
+};
+
+void Box::setWidth(double wid)
+{
+    width = wid;
+}
+
+//注意:printWidth()不是任何类的成员函数
+void printWidth(Box box)
+{
+    /*
+    因为printWidth()是Box的友元,它可以直接访问该类的任何成员
+    */
+    cout << "Width of box: " << box.width << endl;
+}
+
+int main()
+{
+    Box box;
+    box.setWidth(10.0);
+    printWidth(box);
+    
+    return 0;
+}
+

C++内联函数

含义

C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。

对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。

如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。

在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。

优缺点

  • 优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.

  • 缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。

  • 结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!

    另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。

    有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要;比如虚函数和递归函数就不会被正常内联。

    通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。

    虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.

示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+
#include <iostream>
+using namespace std;
+
+inline int Max(int x, int y)
+{
+    return (x > y) ? x : y; 
+}
+
+int main()
+{
+   cout << "Max (20,10): " << Max(20,10) << endl;
+   cout << "Max (0,200): " << Max(0,200) << endl;
+   cout << "Max (100,1010): " << Max(100,1010) << endl;
+   return 0;
+}
+

注意事项

  • 在内联函数中不允许使用循环语句和开关语句
  • 内联函数的定义必须出现在内联函数第一次调用之前
  • 类结构中所在的类说明内部定义的函数是内联函数

C++ this指针

含义

在C++中,this指针是一个特殊指针,它指向当前对象的实例。

在C++中,每个对象都 能通过 this 指针来访问自己的地址。

this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。

当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。

友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。

实例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
#include <iostream>
+
+class MyClass
+{
+private:
+    int value;
+    
+public:
+    void setValue(int value)
+    {
+        this->value = value;
+	}
+    
+    void printValue()
+    {
+        std::cout << "Value: " << this->value << std::endl;
+	}
+};
+
+int main()
+{
+    MyClass obj;
+    obj.setValue(42);
+    obj.printValue();
+    
+    return 0;
+}
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43.jpg" new file mode 100644 index 000000000..dbeeb4d28 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43_hue4c767a73a4c40ef0fc0194b9f009308_62623_250x150_fill_q75_box_smart1.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43_hue4c767a73a4c40ef0fc0194b9f009308_62623_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..31a8cd572 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.f51b7bbe27e63b1967b6cb84fe39aa43_hue4c767a73a4c40ef0fc0194b9f009308_62623_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.jpg" new file mode 100644 index 000000000..dbeeb4d28 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d719c79aa Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..13a3a8c42 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ccfb1917a Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/index.html" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/index.html" new file mode 100644 index 000000000..10043f01d --- /dev/null +++ "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\345\207\275\346\225\260\344\270\223\351\242\230/index.html" @@ -0,0 +1,632 @@ +C素养提升-函数专题 +
Featured image of post C素养提升-函数专题

C素养提升-函数专题

在c语言中,函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。

+
+

函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。

一般形式如下:

<数据类型> <函数名称>(<形式参数说明>)

函数的参数传递

函数之间的参数传递方式:

  • 全局变量
  • 复制传递方式
  • 地址传递方式

1.全局变量

全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。

全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。不建议使用

2.复制传递

调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。

形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。

3.地址传递

按地址传递,实参为变量的地址,而形参为同类型的指针。

被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+
#include <stdio.h>
+
+int str_fun(char *p);
+
+int main(int argc, char *argv[])
+{
+    char s[] = "welcome2023Jiangxi";
+    int n;
+    
+    n = str_fun(s);
+    printf("n=%d %s\n", n, s);
+    
+    return 0;
+}
+
+// char *p = n		我们需要习惯将形参联想等于实参,两端逻辑需要相通
+int str_fun(char *p)
+{
+    int num = 0;
+    while(*p != '\0')
+    {
+        if(*p <= 'z' && *p >= 'a')
+        {
+        	num++;
+            *p -= ' ';
+	    }
+        p++;
+	}
+    return num;
+}
+

image-20230131104155837

函数的传参–数组

  • 全局数组传递方式

  • 复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)

  • 地址传递方式:实参为数组的指针,形参为同类型的指针变量

案例一

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+
#include <stdio.h>
+
+int array_sum(int data[], int n);	//相当于int array_sum(int *data, int n);
+
+int main(int argc, char *argv[])
+{
+        int a[] = {5, 9, 10, 3, 10};
+        int sum = 0;
+
+        sum = array_sum(a,sizeof(a) / sizeof(int));
+
+        printf("sum=%d\n", sum);
+        return 0;
+}
+
+int array_sum(int data[], int n)   // int data[] = a;-->error
+{								
+        int ret = 0;
+        int i;
+
+        for(i = 0; i < n; i++)
+        {
+                ret += data[i]; 
+        }
+        return ret;
+}
+

image-20230202113334614

上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是int data[],此时的int data[]实际就是int *data,使用sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度

案例二

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
// try to write a function,which delete the space character of character string.
+
+#include <stdio.h>
+
+void del_space(char *str);
+
+int main(int argc, char *argv[])
+{       
+        char a[] = "hello world,hello linux!";
+        puts(a);
+        del_space(a);
+        puts(a);
+
+        return 0; 
+}
+void del_space(char *str)
+{       
+        char *p;
+        p = str;
+        while(*str)
+        {
+                if(*str == ' ')
+                {
+                        str++;
+                }
+                else
+                {
+                        *p = *str;
+                        p++;
+                        str++;
+                }
+        }
+        *p = '\0';
+}
+

image-20230202121727967

此处是删除一段字符串中的空格字符,在void del_space()函数中,我们采取的是指针地址传递的形式,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位\0时,代表字符串的末尾,因此我们也需要为赋值*p = '\0';代表末位。

指针函数

1.基本概念

指针函数是指一个函数的返回值为地址量的函数。

2.定义形式

函数指针的定义的一般形式如下:

1
+2
+3
+4
+5
+6
+7
+
<数据类型> * <函数名称>(<参数说明>){
+
+语句序列;
+
+}
+
+`返回值:全局变量的地址 / static变量的地址 / 字符串常量的地址 / 堆的地址`
+

3.示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
// 编写一个指针函数,删除一个字符串中的空格
+
+#include <stdio.h>
+#include <string.h>
+
+char *del_space(char *s);
+
+int main(int argc, char *argv[])
+{
+        char * r;
+        char str[] = "How   ar e  y ou!";
+        
+        r = del_space(str);
+        printf("----%s---\n",r);
+        
+        puts(str);
+        
+        return 0;
+}
+
+char *del_space(char *s)
+{
+        char *p = s;
+        char *r = s;
+        
+        while(*s)
+        {
+                if(*s == ' ')
+                {
+                        s++;
+                }
+                else
+                {
+                        *p = *s;
+                        s++;
+                        p++;
+                }
+        }
+        *p = '\0';
+
+        return r;
+}
+

image-20230214135249007

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
// 编写一个函数,实现两个字符串的连接
+
+#include <stdio.h>
+
+char *mstrcat(char *dest, const char * src);
+
+int main(int argc, char *argv[])
+{
+	char dest[59] = "welcome";
+	char src[] = "makeru";
+	
+	puts(mstrcat(dest,src));
+	puts(dest);
+	
+	return 0;
+}
+
+char *mstrcat(char *dest, const char * src)
+{
+	char *r = dest;
+	while(*dest)
+	{
+		dest++;
+	}
+	while(*src)
+	{
+		*dest = *src;
+		dest++;
+		src++;
+	}
+	*dest = '\0';
+	
+	return r;
+}
+

image-20230214140618531

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
// 编写一个函数,将传入的整型转成字符串
+
+#include <stdio.h>
+
+char * itoa(int n);
+int main(int argc, char *argv[])
+{
+        int n;
+        char s[50], *r;
+
+        printf("input:");
+        scanf("%d",&n);
+
+        r = itoa(s, n);
+
+        puts(r);
+        puts(s);
+
+        return 0;
+}
+
+char * itoa(char *p, int n)
+{
+        int r, i = 0, j;
+        //static char p[50];
+
+        while(n)
+        {
+                r = n % 10;
+                n /= 10;
+                p[i] = r + '0';
+                i++;
+        }
+        p[i] = '\0';
+
+        j = i - 1;
+        i = 0;
+
+        while(i < j)
+        {
+                r = p[i];
+                p[i] = p[j];
+                p[j] = r;
+                j--;
+                i++;
+        }
+
+        return p;
+}
+

image-20230214143612736

递归函数

1.基本概念

递归函数是指一个函数的函数体中直接或间接调用了该函数自身

递归函数调用的执行过程分为两个阶段:

  • 递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。
  • 回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。

2.示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
// 计算n!
+
+#include <stdio.h>
+
+int fac(int n);
+
+int main(int argc, char *argv[])
+{
+	int n;
+	
+	printf("input:");
+	scanf("%d",&n);
+	
+	printf("%d\n", fac(n));
+	
+	return 0;
+}
+
+int fac(int n)
+{
+	if(n == 0 || n == 1)
+		return 1;
+	return n * fac(n-1);
+}
+

image-20230214144903183

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
// 编写一段程序,计算斐波那契序列
+
+#include <stdio.h>
+
+int fib(int n);
+
+int main(int argc, char *argv[])
+{
+    int n = 1;
+    while(n <= 10)
+    {
+        printf("%d ",fib(n));
+        n++;
+	}
+    
+    printf("\n");
+    return 0;
+}
+
+int fib(int n)
+{
+    if(n == 1 || n == 2)
+        return 1;
+    return fib(n-1)+fib(n-2);
+}
+

image-20230214145721633

函数指针

1.基本概念

函数指针用来存放函数的地址,这个地址是一个函数的入口地址

  • 函数名代表了函数的入口地址

2.定义形式

函数指针变量说明的一般形式如下:

1
+2
+3
+4
+
<数据类型> (*<函数指针名称>) (<参数说明列表>);
+
+eg:
+int (*p)(int a, int b);
+

3.函数指针数组

定义:函数指针数组是一个保存若干个函数名的数组。

一般形式如下:

1
+2
+3
+4
+
<数据类型> (*<函数指针数组名称>)(<大小>)(<参数说明列表>);
+
+---<大小>:指函数指针数组元素的个数
+---其他等同普通的函数指针
+

4.示例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
// 编写一段程序,实现qsort()排序的功能
+
+#include <stdio.h>
+
+int compare(const void*, const void *);
+
+int main(int argc, char *argv[])
+{
+        int s[] = {89, 23, 5, 54, 75}, n, i;
+    n = sizeof(s) / sizeof(int);
+    qsort(s, n, sizeof(int), compare);
+
+    for(i = 0;i < n; i++)
+        printf("%d ",s[i]);
+    puts("");
+
+    return 0;
+}
+
+int compare(const void* p, const void *q)
+{
+        return (*(int *)p - *(int *)q);
+}
+

image-20230214173053208

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9.jpg" new file mode 100644 index 000000000..31568e3bb Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9_hu70b9966484078ba6992d2596edd97753_49429_250x150_fill_q75_box_smart1.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9_hu70b9966484078ba6992d2596edd97753_49429_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..b5789e9a4 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.494059b41fc3541ab7cad1bfd82ff4d9_hu70b9966484078ba6992d2596edd97753_49429_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.jpg" new file mode 100644 index 000000000..31568e3bb Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_120x120_fill_q75_box_smart1.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..1f24139ad Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_1600x0_resize_q75_box.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..05bb9f550 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_1600x0_resize_q75_box.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_800x0_resize_q75_box.jpg" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..0cedca314 Binary files /dev/null and "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/cover_hu70b9966484078ba6992d2596edd97753_49429_800x0_resize_q75_box.jpg" differ diff --git "a/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/index.html" "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/index.html" new file mode 100644 index 000000000..99c6c1c0f --- /dev/null +++ "b/p/c\347\264\240\345\205\273\346\217\220\345\215\207-\346\214\207\351\222\210\344\270\223\351\242\230/index.html" @@ -0,0 +1,585 @@ +C素养提升-指针专题 +
Featured image of post C素养提升-指针专题

C素养提升-指针专题

在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。

+
+

指针

在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。

在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。

地址和变量

在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址

编译或函数调用时为其分配内存单元。

变量是对程序中数据存储空间的抽象。

指针变量的说明

一般形式如下:

1
+2
+3
+
<存储类型> <数据类型> * <指针变量名>;
+
+例如,char *pName;
+

指针的存储类型是指针变量本身的存储类型。

指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。

指针在说明的同时,也可以被赋值初值,成为指针的初始化

一般形式如下:

1
+2
+3
+
<存储类型> <数据类型> * <指针变量名> = <地址量>;
+
+例如:int a, *pa = &a;
+

在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。

1
+2
+
int a = 3;
+int *pa = &a;	//相当于:int * pa; pa = &a;
+

下面是一个程序示例:

1
+2
+3
+4
+5
+6
+7
+8
+9
+
#include <stdio.h>
+int main(int argc, char *argv[])
+{
+        int a = 10;
+        int * p;
+        p = &a;
+        printf("p:%p a:%p\n",p,&a);
+        return 0;
+}
+

可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是0x7fff64003e1c

image-20230112173909015

下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
#include <stdio.h>
+int main(int argc, char *argv[])
+{
+        int a = 10;
+        int * p;
+        p = &a;
+        printf("&p:%p sizeof(p):%d\n",&p,sizeof(p));
+        printf("p:%p a:%p\n",p,&a);
+        return 0;
+}
+

image-20230112175033147

编译查看结果,可以发现上述的p = &a是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的0x7ffc915b44e0

一般我们清楚,在指针中*p是作为取值,而&p则是取地址,我们再次对程序作出修改:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
#include <stdio.h>
+int main(int argc, char *argv[])
+{
+        int a = 10;
+        int * p;
+        p = &a;
+        printf("&p:%p sizeof(p):%d\n",&p,sizeof(p));
+        printf("p:%p a:%p\n",p,&a);
+        printf("%d %p %d \n",*p,*(&p),*(*(&p)));
+        return 0;
+}
+

image-20230112182106265

那么我们可以看到a = *p = *(*(&p)) = 10,仔细理解*(*(&p)),也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是p = *(&p),此时对其取地址,可以发现和p所对应的地址相同,此时再对*(*(&p))取值,那么也就是对应的一个数据,同理,&p = &(*(&p))也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。

指针的目标

指针指向的内存区域中的数据成为指针的目标。

如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。

在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。

引入指针

引入指针要注意程序中的px, *px和&px三种表示方法的不同意义。设px为一个指针,则:

px — 指针变量,它的内容是地址量

*px — 指针所指向的对象,它的内容是数据

&px — 指针变量所占用的存储区域的地址,是个常量

指针的赋值

指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。

向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)

指针赋值运算常见的有以下几种形式:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针:
+double x = 15, *px;
+px = &x;
+
+// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量:
+float a, *px, *py;
+px = &a;
+py = px;
+
+// 3、把一个数据的地址赋给具有相同数据类型的指针:
+int a[20], *pa;
+pa = a;	//等价 pa = &a[0]
+

下面是一个程序案例:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
#include <stdio.h>
+int main(int argc, char *argv[])
+{
+        int a = 10;
+        int * p;
+        int * q;
+
+        p = &a;
+        q = &a;
+
+        printf("&p:%p %d\n",&p,sizeof(p));
+        printf("p:%p a:%p\n",p,&a);
+        printf("%d %d\n",a,*p);
+
+        printf("\n\n&q:%p %d\n",&q,sizeof(q));
+        printf("%p %d\n",q,*q);
+
+        return 0;
+}
+

image-20230112194158128

在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,),也就是说指针p和指针q都是指向目标变量a。

指针运算

指针运算是以指针变量所存放的地址量作为运算量而进行的运算

指针运算的实质就是地址的计算

指针运算的种类是有限的,它只能进行赋值运算、算术运算和关系运算。

运算符计算形式意 义
+px+n指针向地址大的方向移动n个数据
-px-n指针向地址小的方向移动n个数据
++px++指针向地址小的方向移动1个数据
px–指针向地址小的方向移动1个数据
-px-py两个指针之间相隔数据元素的个数
  • 不同数据类型的两个指针实行加减整数运算是无意义的。

  • px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n

  • px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n

  • px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。

  • 两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。

  • 指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。

注意:

两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误,示例如下:

image-20230112210030039

正确的运行示例:

image-20230112210312170

这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数

下面是一些指针运算的示例:

image-20230112212116348

上述程序重要的就是理顺指针的关系以及运算符优先级问题。


知识扩展:

在32位系统与64位系统下,不同数据类型所对应的字节数—>

数据类型32位64位备注
char11
short22
int44
long4832位与64位不同
float44
char *48其他指针类型如long *,int *也是如此
long long88
double88
long double10/1210/16有效位10字节。32位为了对其实际分配12字节;64位分配16字节

指针与数组

指针对数组的访问

在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。

一维数组的数组名为以为数组的指针(起始地址)。

例如:

1
+
double x[8];
+

因此,x为x数组的起始地址。

设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:

x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]:访问数组第i+1个数组元素,下面参照示例:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5};
+        int *p, i, n;
+
+        p = a;
+        n = sizeof(a) / sizeof(int);
+
+        printf("%d\n",n);
+        printf("%p %p %p\n",a, a+1, a+2);
+        
+        for(i = 0; i < n; i++)
+                printf("%d %d %d %d\n",a[i],*(p+i),*(a+i),p[i]);
+        puts("");
+        return 0;
+}
+

image-20230113163021566

那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。

注意:

  • 指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量

  • 但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量

程序案例

程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5};
+        int *p, *q, t;
+
+        int n = sizeof(a) / sizeof(int);
+        
+        p = a;
+        q = &a[n-1];
+
+
+        while(p < q)
+        {
+                t =*p;
+                *p = *q;
+                *q = t;
+                p++;
+                q--;
+        }
+
+        for(t = 0;t < n;t++)
+        {
+                printf("%d ",a[t]);
+        }  
+        puts("");
+        return 0;
+}
+

image-20230113170338589

程序2

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5};
+        int *p, i, n;
+
+        p = a;
+        n = sizeof(a) / sizeof(int);
+
+        printf("%d\n",n);
+        printf("%p %p %p\n",a, a+1, a+2);
+
+        for(i = 0; i < n; i++)
+                printf("%d %d %d %d\n",a[i],*(p+i),*(a+i),p[i]);
+        puts("");
+
+        p++;
+        printf("%d\n",p[1]);
+        return 0;
+}
+

image-20230113171028194

这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2

知识点:

数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)

指针与二维数组

二维数组的性质

多维数组就是具有两个或两个以上下标的数组。

在c语言中,二维数组的元素连续存储,按行优先存取。

下面看程序案例:

案例一:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[3][2] = {{1, 6}, {9, 12}, {61, 12}};
+        int *p, i, n;
+
+        n = sizeof(a) / sizeof(int);
+        printf("%d\n",n);
+        p = a[0];
+        printf("%d\n",sizeof(a[0]));
+        
+        printf("%p %p\n", p, p+1);
+        printf("%p %p\n", a, a+1);
+        
+        for(i = 0;i < n; i++)
+                printf("%d ", *(p+i));
+        puts("");
+        
+        return 0;
+}
+

image-20230113173618278

上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。

案例二:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[3][2] = {{1, 6}, {9, 12}, {61, 12}};
+        int *p, i, n;
+
+        n = sizeof(a) / sizeof(int);
+
+        printf("%p %p\n", a, a+1);
+        printf("%p %p\n", a[0], a[0]+1);
+    	printf("%p %p\n", *a, *a+1);
+
+        return 0;
+}
+

image-20230113195318122

从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。

行指针(数组指针)

二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址

**存储行地址的指针变量,叫做行指针变量。**形式如下:

<存储类型> <数据类型> (*<指针变量名>)[表达式];

例如:int a[2] [3]; int (*p)[3]

注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。

我们用一个程序案例来解释:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[3][2] = {{1, 6}, {9, 12}, {61, 12}};
+        int (*p)[2];
+
+        p = a;
+
+        printf("%p %p\n",a ,a+1);
+        printf("%p %p\n",p ,p+1);
+
+        printf("%d, %d, %d, %d\n",a[1][1], p[1][1], *(*(a+1)), *(*((p+1)+1)));  
+        printf("%d %d\n",*(*(a+1)),*(*((a+1)+1)));
+   		printf("%p %p\n",&(*(a+1)),&(*((a+1)+1)));
+        return 0;
+}
+

image-20230113203626795

根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&,代表的就是取地址【&( *(a+1))】。

字符指针与字符串

字符指针的定义

C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。

字符指针的初始化

**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。

1
+2
+
char str[] = "Hell World";
+char *p = str;
+

在C编程中,当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。

1
+2
+
char *p = "Hello World";	//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址
+*p = 'h';	//错误,字符串常量不能修改
+

程序案例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        char *p1 = "hello world!";
+        char *p2 = "hello world!";
+
+        printf("&p1=%p %p %s\n", &p1, p1, p1);
+        printf("&p2=%p %p %s\n", &p2, p2, p2);
+        return 0;
+
+}
+

image-20230114101732695

此处我们可以看到,由于字符指针的内容都是hello world!,也就是申请了一段字符串空间存取的内容为hello world!,当我们打印字符指针p1和p2指向的地址时可以发现都指向了0x4006a4,接着我们打印指针存放的地址,可以发现&p1=0x7ffc8d801cd8&p2=0x7ffc8d801ce0,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)**

指针数组

指针数组的定义

所谓指针数组是指若干个具有相同存储类型和数据类型的指针变量构成的集合。

指针数组的一般说明形式:

<存储类型> <数据类型> *<指针数组名>[<大小>];

指针数组名表示该指针数组的起始地址

指针数组的声明

声明一个指针数组:

1
+
double *pa[2], a[2][3];
+

把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:

1
+2
+3
+4
+
pa[0] = a[0];	//等价pa[0] = &a[0][0]
+pa[1] = a[1];	//等价pa[1] = &a[1][0]
+
+//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0]
+

程序案例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int *p[3];
+        int a[] = {3, 6, 1, 7, 10};
+
+        p[0] = a;
+        p[1] = a + 1;
+        p[2] = a + 3;
+
+        printf("%d %d %d\n",a[0], a[1], a[3]);
+        printf("%d %d %d\n",*(p[0]),*(p[1]),*(p[2]));
+
+        printf("%p %p\n",p[0],p[1]);
+        printf("%p %p\n",&p[0],&p[1]);
+        return 0;
+}
+

image-20230114111849051

问:指针数组名相当于什么样的指针? 答:二级指针。

多级指针

多级指针的定义

把一个指向指针变量的指针变量,称为多级指针。

对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。

对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。

二级指针变量的说明形式如下:

<存储类型> <数据类型> **<指针名>;

多级指针的运算

**指针变量加1,是向地址大的方向移动一个目标数据。**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。

比如:int **p; p+1移动一个int *变量所占的内存空间。

程序案例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[] = {3, 6, 9};
+        int *p[2] = {&a[0],&a[1]};
+
+        int **q;
+
+        q = &p[0];
+        q = p;
+
+        printf("%d %d\n",a[0],a[1]);
+        printf("%d %d\n",*p[0],*p[1]);
+
+        printf("%d %d %d\n",a[0],*p[0],**q);
+
+        return 0;
+}
+

image-20230114171007367

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        char *s[] = {"apple", "pear", "potato"};
+
+        int i, n;
+        n = sizeof(s) / sizeof(char *);
+        printf("%d %d %d\n",n,sizeof(s),sizeof(char *));
+
+        return 0;
+}
+

image-20230114172259973

void指针

void指针的定义

void指针是一种不能确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量。

一般形式为:

void * <指针变量名>

对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。

程序案例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int m = 10;
+        double n = 3.14;
+        void *p, *q;
+
+        p = &m; //(void *) &m
+        printf("%d %d\n",m,*(int *)p);
+
+        q = &n; //(void *)&n
+        printf("%.2lf %.2lf\n",n, *(double *)q);
+        return 0;
+}
+

image-20230114174233538

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
#include <stdio.h>
+int main(int argc,char *argv[])
+{
+        int a[] = {6, 3, 2, 7, 9, 6};
+        int i, n;
+        void *p;
+
+        p = a;
+        n = sizeof(a) / sizeof(int);
+        for(i = 0;i < n;i++)
+                printf("%d ",*((int *)p +i));
+        puts("");
+        return 0;
+}
+

image-20230114175011554

此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要(int *)p进行强转,之后对于用户的算数运算就没什么问题了。

const修饰指针

常量化指针目标表达式

一般说明形式如下:

const <数据类型> * <指针变量名>[= <指针运算表达式>]

常量化指针目标是限制通过指针改变其目标的数值,但<指针变量> --->存储的地址值可以修改。

常量化指针变量

一般说明形式如下:

<数据类型> * const <指针变量名>[= <指针运算表达式>]

使得<指针变量>存储的地址值不能修改。但可以通过* <指针变量名>可以修改指针所指向变量的数值。

常量化指针变量及目标表达式

一般说明形式如下:

const <数据类型> * const <指针变量名>[= <指针运算表达式>]

常量化指针变量及目标表达式,使得既不可以修改<指针变量名>的地址,也不可以通过* <指针变量名>修改指针所指向变量的值。

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8.jpg" new file mode 100644 index 000000000..079b969ef Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8_hu988a92fc47be5a32e45d6a6ece551f64_92962_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8_hu988a92fc47be5a32e45d6a6ece551f64_92962_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..82c58312b Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.28dfb24683a14e65f3e7519c0ff98eb8_hu988a92fc47be5a32e45d6a6ece551f64_92962_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.jpg" new file mode 100644 index 000000000..079b969ef Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..043be79c1 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f59e30d2e Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9db577171 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/index.html" new file mode 100644 index 000000000..6abc53049 --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\220\214\346\255\245gitee\351\225\234\345\203\217\344\273\223\345\272\223\350\207\252\345\212\250\345\214\226\350\204\232\346\234\254/index.html" @@ -0,0 +1,164 @@ +Github同步Gitee镜像仓库自动化脚本 +
Featured image of post Github同步Gitee镜像仓库自动化脚本

Github同步Gitee镜像仓库自动化脚本

在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。

+
+

Github同步Gitee镜像仓库自动化脚本


前言

在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。

什么是Hub Mirror Action?

image-20230411153729450

1.介绍

Hub Mirror Action是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。

2.用法

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
steps:
+- name: Mirror the Github organization repos to Gitee.
+  uses: Yikun/hub-mirror-action@master
+  with:
+    src: github/kunpengcompute
+    dst: gitee/kunpengcompute
+    dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
+    dst_token: ${{ secrets.GITEE_TOKEN }}
+    account_type: org
+    # src_account_type: org
+    # dst_account_type: org
+

附:详细使用案例请查看官方仓库 https://github.com/Yikun/hub-mirror-action

配置步骤

1.生成密钥对

我们先在本地使用git命令行打开终端,输入如下命令:

1
+
ssh-keygen -t rsa -f ~/Documents/ssh-key/id_rsa
+

注:请确保文件夹~/Documents/ssh-key/存在,当然你也可以选择放置在其他地方

过程中一路回车即可,注意不要设置密码。

image-20230411154330166

image-20230411155124878

2.GitHub私钥配置

首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。

image-20230411154716849

  • 依次点击Settings->Secrets and variables->Actions

  • 点击New respository secret,创建一个名为GITEE_PRIVATE_KEY的secret,值为我们之前生成的密钥对中的私钥(id_rsa)

image-20230411155314101

3.Gitee公钥配置

我们打开Gitee账号,进入Settings->安全设置->SSH公钥

添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)

image-20230411155846562

4.Gitee生成私人令牌

image-20230411155958898

令牌名称随意,同时复制生成的令牌值。

image-20230411160127393

5.Github绑定Gitee令牌

  • 依次点击Settings->Secrets and variables->Actions

  • 点击New respository secret,创建一个名为GITEE_TOKEN的secret,值为Gitee生成的令牌值

image-20230411160340721

6.编写CI脚本

ci_bot仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:

1
+2
+3
+4
+
.ci_bot/
+    |——.github
+    	|——workflows
+    		|——Sync.yml
+

Sync.yml文件中,添加以下代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
name: Sync Github Repos To Gitee
+
+on: [ push, delete, create ]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+
+    - name: Sync Github Repos To Gitee  # 名字随便起
+      uses: Yikun/hub-mirror-action@master  # 使用Yikun/hub-mirror-action
+      with:
+        src: github/kurisaW  # 源端账户名(github)
+        dst: gitee/kurisaW  # 目的端账户名(gitee)
+        dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}  # SSH密钥对中的私钥
+        dst_token:  ${{ secrets.GITEE_TOKEN }}  # Gitee账户的私人令牌
+        account_type: user  # 账户类型
+        clone_style: "https"  # 使用https方式进行clone,也可以使用ssh
+        debug: true  # 启用后会显示所有执行命令
+        force_update: true  # 启用后,强制同步,即强制覆盖目的端仓库
+        static_list: "kurisaW_docs"  # 静态同步列表,在此填写需要同步的仓库名称,可填写多个
+        timeout: '600s'  # git超时设置,超时后会自动重试git操作
+

保存退出后,将本次修改push到远端仓库。

查看Action运行情况:

image-20230411161143741

7.多仓库同步推送

如果你想同时同步多个仓库,只需要完成如下修改

1
+
static_list 默认为'', 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。
+

image-20230411163307283

image-20230411163135259

8.定时运行脚本

为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:

修改Sync.yml文件:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+
name: Sync Github Repos To Gitee
+
+on: 
+  schedule:
+    - cron: '0 0 * * *'
+  push:
+    branches: [ main ]
+  delete:
+    branches: [ main ]
+  create:
+    branches: [ main ]
+    
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+
+    - name: Sync Github Repos To Gitee  # 名字随便起
+      uses: Yikun/hub-mirror-action@master  # 使用Yikun/hub-mirror-action
+      with:
+        src: github/kurisaW  # 源端账户名(github)
+        dst: gitee/kurisaW  # 目的端账户名(gitee)
+        dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}  # SSH密钥对中的私钥
+        dst_token:  ${{ secrets.GITEE_TOKEN }}  # Gitee账户的私人令牌
+        account_type: user  # 账户类型
+        clone_style: "https"  # 使用https方式进行clone,也可以使用ssh
+        debug: true  # 启用后会显示所有执行命令
+        force_update: true  # 启用后,强制同步,即强制覆盖目的端仓库
+        static_list: "kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io"  # 静态同步列表,在此填写需要同步的仓库名称,可填写多个
+        timeout: '600s'  # git超时设置,超时后会自动重试git操作
+

也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。

image-20230411173142865

总结

通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 11, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b.jpg" new file mode 100644 index 000000000..486f93a40 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..ce6afdfec Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.646d3a65383974938f78d652ef8f980b_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.jpg" new file mode 100644 index 000000000..486f93a40 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..6288100a4 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c836614ce Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..5fb61a07a Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/ssh-config.png" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/ssh-config.png" new file mode 100644 index 000000000..fdafc88bc Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/ssh-config.png" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/valid-ssh.png" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/valid-ssh.png" new file mode 100644 index 000000000..9ffe68e48 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/figure/valid-ssh.png" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/index.html" new file mode 100644 index 000000000..221484fcc --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\222\214gitlab\345\220\214\346\227\266\344\275\277\347\224\250ssh/index.html" @@ -0,0 +1,60 @@ +【Git版本控制】Github和Gitlab同时使用ssh +
Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh

【Git版本控制】Github和Gitlab同时使用ssh

最近在使用WSL时会同时用到GitHub和Gitlab,因此与传统配置ssh方式有些不一样的地方,这里特别记录一下

+
+

前言

最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下

本地生成公私密钥

首先确保把之前的 ssh 信息清除,也可以将整个 ~/.ssh 目录删除

1
+
rm -rf ~/.ssh/*
+

我们分别生成 Github 和 Gitlab账号的 SSH 密钥

  • Github 生成密钥
1
+
ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa
+
  • Gitlab 生成密钥
1
+
ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa
+

注意不要选择其他操作,一路回车即可

此时打开 ~/.ssh/ 目录可以看到生成了四个文件:github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub

其中 .pub 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存

远程仓库 SSH 填写公钥密钥

我们先打开 Github 的 Settings选项,然后选择 SSH and GPG keys->New SSH keyTitle可以随意拟定,Key需要查看刚刚的 github_id-rsa.pub 文件,并且复制到 Gitlab 的key一栏中;

Gitlab 的操作方式与 Github 类似,具体步骤:

打开 Gitlab -> 用户设置 -> SSH密钥 ,在密钥一栏填入 gitlab_id-rsa.pub文件中的具体值,标题自拟即可。

配置不同 Host 的 SSH Key

回到 ~/.ssh/ 目录下,并且创建一个名为 config 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
#github
+Host github.com
+    Hostname ssh.github.com
+    Port 443
+    User git
+    IdentityFile ~/.ssh/github_id-rsa
+
+#gitlab
+host git.rt-thread.com
+    Hostname git.rt-thread.com
+    User git
+    IdentityFile ~/.ssh/gitlab_id-rsa
+

验证

使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置

  • Github SSH 验证
1
+
ssh -T git@github.com
+
  • Gitlab SSH 验证
1
+
ssh -T git@rt-thread.com
+

如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功

+Licensed under CC BY-NC-SA 4.0
+Last updated on Sep 16, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4.jpg" new file mode 100644 index 000000000..8a9d91695 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4_hucbce8390de2ea0a35e5136165fc15f47_34419_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4_hucbce8390de2ea0a35e5136165fc15f47_34419_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..7f9da688c Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.05ee6ff2f84596a1f677a301930970c4_hucbce8390de2ea0a35e5136165fc15f47_34419_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.jpg" new file mode 100644 index 000000000..8a9d91695 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..53a143676 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..22d73c9f5 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..d6c20d05f Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/index.html" new file mode 100644 index 000000000..208c84409 --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266github\345\233\276\345\272\212\346\234\215\345\212\241action---\350\207\252\345\212\250\347\233\221\350\247\206\345\233\276\345\272\212\344\273\223\345\272\223\347\232\204\347\233\256\345\275\225\344\270\213\347\232\204\346\226\207\344\273\266\346\225\260/index.html" @@ -0,0 +1,163 @@ +【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数 +
Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数

【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数

当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息

+
+

前言

最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是Github + Typora的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.

所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。

具体流程

当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。

1. 创建GitHub工作流文件

在GitHub仓库中,转到.github/workflows目录并创建一个新文件,比如file_count.yml。该文件将定义运行自动化操作的工作流。

2. 定义工作流

file_count.yml文件中,添加以下代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
name: File Count Reminder
+
+on:
+  schedule:
+    - cron: "0 0 * * *" # Runs every day at midnight UTC
+
+jobs:
+  count-files:
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Check out code
+        uses: actions/checkout@v2
+
+      - name: Set up Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: '3.10' # Replace with the desired Python version
+
+      - name: Count files and send email
+        run: |
+          pip install -r requirements.txt
+          python send_email.py ${{ secrets.GITHUB_TOKEN }}          
+

3. 创建requirements.txt文件

在GitHub仓库中创建一个名为requirements.txt的文件,并将以下内容添加到文件中:

1
+
smtplib
+

4. 创建send_email.py文件

在GitHub仓库中创建一个名为send_email.py的文件,并将以下代码添加到文件中:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
import os
+import smtplib
+from email.mime.text import MIMEText
+from email.header import Header
+
+def count_files(directory):
+    file_count = 0
+    for root, dirs, files in os.walk(directory):
+        file_count += len(files)
+    return file_count
+
+def send_email(github_token, recipient, file_count):
+    smtp_server = 'smtp.gmail.com'
+    smtp_port = 587
+
+    subject = 'File Count Reminder'
+    content = f'The repository has {file_count} files.'
+
+    message = MIMEText(content, 'plain', 'utf-8')
+    message['From'] = Header('GitHub Action')
+    message['To'] = Header(recipient)
+    message['Subject'] = Header(subject)
+
+    try:
+        server = smtplib.SMTP(smtp_server, smtp_port)
+        server.starttls()
+        server.login('githubaction@gmail.com', github_token)
+        server.sendmail('githubaction@gmail.com', recipient, message.as_string())
+        server.quit()
+        print("Email reminder sent to", recipient)
+    except Exception as e:
+        print("Failed to send email:", str(e))
+
+repository_path = '.'  # Replace with the path to your repository if needed
+file_limit = 999
+
+file_count = count_files(repository_path)
+if file_count > file_limit:
+    github_token = os.environ.get('INPUT_GITHUB_TOKEN')
+    default_email = os.environ.get('GITHUB_ACTOR') + '@users.noreply.github.com'
+
+    send_email(github_token, default_email, file_count)
+else:
+    print("The repository has", file_count, "files. No reminder needed.")
+

使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 31, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde.jpg" new file mode 100644 index 000000000..e3e9b65e2 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde_hub0dc5de02b67b4945e49bf20f42f29b6_29697_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde_hub0dc5de02b67b4945e49bf20f42f29b6_29697_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c91bb3380 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.7740e8b98f3ae83d0fa403725a23bfde_hub0dc5de02b67b4945e49bf20f42f29b6_29697_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.jpg" new file mode 100644 index 000000000..e3e9b65e2 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..914530607 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f6e619a9c Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..17767eafb Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/index.html" new file mode 100644 index 000000000..27a681636 --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266git\345\221\275\344\273\244\350\257\246\350\247\243/index.html" @@ -0,0 +1,257 @@ +【Git版本控制】Git命令详解 +
Featured image of post 【Git版本控制】Git命令详解

【Git版本控制】Git命令详解

Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 回撤这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而版本管理工具能记录每次的修改,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。

+
+

前言

Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 回撤这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而版本管理工具能记录每次的修改,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。

下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。

展示帮助信息

1
+
git help -g
+

The command output as below:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
The common Git guides are:
+   attributes          Defining attributes per path
+   cli                 Git command-line interface and conventions
+   core-tutorial       A Git core tutorial for developers
+   cvs-migration       Git for CVS users
+   diffcore            Tweaking diff output
+   everyday            A useful minimum set of commands for Everyday Git
+   glossary            A Git Glossary
+   hooks               Hooks used by Git
+   ignore              Specifies intentionally untracked files to ignore
+   modules             Defining submodule properties
+   namespaces          Git namespaces
+   repository-layout    Git Repository Layout
+   revisions           Specifying revisions and ranges for Git
+   tutorial            A tutorial introduction to Git
+   tutorial-2          A tutorial introduction to Git: part two
+   workflows           An overview of recommended workflows with Git
+
+'git help -a' and 'git help -g' list available subcommands and some concept guides. See 'git help <command>' or 'git help <concept>' to read about a specific subcommand or concept.
+

回到远程仓库的状态

抛弃本地所有的修改,回到远程仓库的状态。

1
+
git fetch --all && git reset --hard origin/master
+

重设第一个 commit

也就是把所有的改动都重新放回工作区,并清空所有的 commit,这样就可以重新提交第一个 commit 了

1
+
git update-ref -d HEAD
+

查看冲突文件列表

展示工作区的冲突文件列表

1
+
git diff --name-only --diff-filter=U
+

展示工作区和暂存区的不同

输出工作区暂存区的 different (不同)。

1
+
git diff
+

还可以展示本地仓库中任意两个 commit 之间的文件变动:

1
+
git diff <commit-id> <commit-id>
+

展示暂存区和最近版本的不同

输出暂存区和本地最近的版本 (commit) 的 different (不同)。

1
+
git diff --cached
+

展示暂存区、工作区和最近版本的不同

输出工作区暂存区 和本地最近的版本 (commit) 的 different (不同)。

1
+
git diff HEAD
+

快速切换到上一个分支

1
+
git checkout -
+

删除已经合并到 master 的分支

1
+
git branch --merged master | grep -v '^\*\|  master' | xargs -n 1 git branch -d
+

展示本地分支关联远程仓库的情况

1
+
git branch -vv
+

关联远程分支

关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。

1
+
git branch -u origin/mybranch
+

或者在 push 时加上 -u 参数

1
+
git push origin/mybranch -u
+

列出所有远程分支

-r 参数相当于:remote

1
+
git branch -r
+

列出本地和远程分支

-a 参数相当于:all

1
+
git branch -a
+

查看远程分支和本地分支的对应关系

1
+
git remote show origin
+

远程删除了分支本地也想删除

1
+
git remote prune origin
+

创建并切换到本地分支

1
+
git checkout -b <branch-name>
+

从远程分支中创建并切换到本地分支

1
+
git checkout -b <branch-name> origin/<branch-name>
+

删除本地分支

1
+
git branch -d <local-branchname>
+

删除远程分支

1
+
git push origin --delete <remote-branchname>
+

或者

1
+
git push origin :<remote-branchname>
+

重命名本地分支

1
+
git branch -m <new-branch-name>
+

查看标签

1
+
git tag
+

展示当前分支的最近的 tag

1
+
git describe --tags --abbrev=0
+

查看标签详细信息

1
+
git tag -ln
+

本地创建标签

1
+
git tag <version-number>
+

默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:

1
+
$ git tag -a <version-number> -m "v1.0 发布(描述)" <commit-id>
+

推送标签到远程仓库

首先要保证本地创建好了标签才可以推送标签到远程仓库:

1
+
git push origin <local-version-number>
+

一次性推送所有标签,同步到远程仓库:

1
+
git push origin --tags
+

删除本地标签

1
+
git tag -d <tag-name>
+

删除远程标签

1
+
git push origin --delete tag <tagname>
+

切回到某个标签

一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:

1
+
git checkout -b branch_name tag_name
+

放弃工作区的修改

1
+
git checkout <file-name>
+

放弃所有修改:

1
+
git checkout .
+

恢复删除的文件

1
+2
+3
+
git rev-list -n 1 HEAD -- <file_path> #得到 deleting_commit
+
+git checkout <deleting_commit>^ -- <file_path> #回到删除文件 deleting_commit 之前的状态
+

以新增一个 commit 的方式还原某一个 commit 的修改

1
+
git revert <commit-id>
+

回到某个 commit 的状态,并删除后面的 commit

和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit

1
+2
+3
+4
+5
+6
+7
+
git reset <commit-id>  #默认就是-mixed参数。
+
+git reset --mixed HEAD^  #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。
+
+git reset --soft HEAD~3  #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可  
+
+git reset --hard <commit-id>  #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容
+

修改上一个 commit 的描述

如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit

1
+
git commit --amend
+

查看 commit 历史

1
+
git log
+

查看某段代码是谁写的

blame 的意思为‘责怪’,你懂的。

1
+
git blame <file-name>
+

显示本地更新过 HEAD 的 git 命令记录

每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。

1
+
git reflog
+

修改作者名

1
+
git commit --amend --author='Author Name <email@address.com>'
+

修改远程仓库的 url

1
+
git remote set-url origin <URL>
+

增加远程仓库

1
+
git remote add origin <remote-url>
+

列出所有远程仓库

1
+
git remote
+

查看两个星期内的改动

1
+
git whatchanged --since='2 weeks ago'
+

把 A 分支的某一个 commit,放到 B 分支上

这个过程需要 cherry-pick 命令,参考

1
+
git checkout <branch-name> && git cherry-pick <commit-id>
+

给 git 命令起别名

简化命令

1
+2
+3
+4
+5
+
git config --global alias.<handle> <command>
+
+比如:git status 改成 git st,这样可以简化命令
+
+git config --global alias.st status
+

存储当前的修改,但不用提交 commit

详解可以参考廖雪峰老师的 git 教程

1
+
git stash
+

保存当前状态,包括 untracked 的文件

untracked 文件:新建的文件

1
+
git stash -u
+

展示所有 stashes

1
+
git stash list
+

回到某个 stash 的状态

1
+
git stash apply <stash@{n}>
+

回到最后一个 stash 的状态,并删除这个 stash

1
+
git stash pop
+

删除所有的 stash

1
+
git stash clear
+

从 stash 中拿出某个文件的修改

1
+
git checkout <stash@{n}> -- <file-path>
+

展示所有 tracked 的文件

1
+
git ls-files -t
+

展示所有 untracked 的文件

1
+
git ls-files --others
+

展示所有忽略的文件

1
+
git ls-files --others -i --exclude-standard
+

强制删除 untracked 的文件

可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,注意两点

  1. clean 后,删除的文件无法找回
  2. 不会影响 tracked 的文件的改动,只会删除 untracked 的文件
1
+
git clean <file-name> -f
+

强制删除 untracked 的目录

可以用来删除新建的目录,注意:这个命令也可以用来删除 untracked 的文件。详情见上一条

1
+
git clean <directory-name> -df
+

展示简化的 commit 历史

1
+
git log --pretty=oneline --graph --decorate --all
+

把某一个分支导出成一个文件

1
+
git bundle create <file> <branch-name>
+

从包中导入分支

新建一个分支,分支内容就是上面 git bundle create 命令导出的内容

1
+
git clone repo.bundle <repo-dir> -b <branch-name>
+

执行 rebase 之前自动 stash

1
+
git rebase --autostash
+

从远程仓库根据 ID,拉下某一状态,到本地分支

1
+
git fetch origin pull/<id>/head:<branch-name>
+

详细展示一行中的修改

1
+
git diff --word-diff
+

清除 gitignore 文件中记录的文件

1
+
git clean -X -f
+

展示所有 alias 和 configs

注意: config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config

1
+2
+
git config --local --list (当前目录)
+git config --global --list (全局)
+

展示忽略的文件

1
+
git status --ignored
+

commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit

1
+
git log Branch1 ^Branch2
+

在 commit log 中显示 GPG 签名

1
+
git log --show-signature
+

删除全局设置

1
+
git config --global --unset <entry-name>
+

新建并切换到新分支上,同时这个分支没有任何 commit

相当于保存修改,但是重写 commit 历史

1
+
git checkout --orphan <branch-name>
+

展示任意分支某一文件的内容

1
+
git show <branch-name>:<file-name>
+

clone 下来指定的单一分支

1
+
git clone -b <branch-name> --single-branch https://github.com/user/repo.git
+

clone 最新一次提交

只会 clone 最近一次提交,将减少 clone 时间

1
+
git clone --depth=1 https://github.com/user/repo.git
+

忽略某个文件的改动

关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动

1
+
git update-index --assume-unchanged path/to/file
+

恢复 track 指定文件的改动

1
+
git update-index --no-assume-unchanged path/to/file
+

忽略文件的权限变化

不再将文件的权限变化视作改动

1
+
git config core.fileMode false
+

以最后提交的顺序列出所有 Git 分支

最新的放在最上面

1
+
git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/
+

在 commit log 中查找相关内容

通过 grep 查找,given-text:所需要查找的字段

1
+
git log --all --grep='<given-text>'
+

把暂存区的指定 file 放到工作区中

不添加参数,默认是 -mixed

1
+
git reset <file-name>
+

强制推送

1
+
git push -f <remote-name> <branch-name>
+
+Licensed under CC BY-NC-SA 4.0
+Last updated on Mar 17, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0.jpg" new file mode 100644 index 000000000..2c6c7b608 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0_hu3f010b25b875bbae5690e71033d3b645_14048_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0_hu3f010b25b875bbae5690e71033d3b645_14048_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..652ea7aef Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.21dc51297c2eccf278337df762fe25d0_hu3f010b25b875bbae5690e71033d3b645_14048_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.jpg" new file mode 100644 index 000000000..2c6c7b608 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..510a08fad Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..1bdc8391c Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..1a14179c8 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/cover_hu3f010b25b875bbae5690e71033d3b645_14048_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/index.html" new file mode 100644 index 000000000..f72b7229e --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\344\275\277\347\224\250tortoisegit\344\270\200\351\224\256\346\211\230\347\256\241\345\267\245\347\250\213\344\273\243\347\240\201\345\217\212\347\211\210\346\234\254\346\216\247\345\210\266/index.html" @@ -0,0 +1,45 @@ +【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制 +
Featured image of post 【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制

【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制

TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。

+
+

一、了解TortoiseGit

TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。

由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。

TortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。

它是在GPL下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。

二、安装GIit及TortoiseGit

在这里插入图片描述

image-20220720090147944

  • 同时下载语言包

当然这里也有百度网盘链接,也可点击下方链接进行下载

链接:https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs +提取码:dzbs

image-20220720090721507

三、TortoiseGit配置

完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项

image-20220720091049882

这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文

image-20220720091218159

配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:

image-20220720091439829

点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):

1
+2
+
[credential]
+  helper = store
+

完成后保存,关闭记事本,确定即可。

  则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。

  如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。

四、添加GitHub SSH Keys及密钥上传

首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\TortoiseGit\bin\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)

image-20220720092721281 +image-20220720093308539

然后复制下方公钥,

image-20220720093236525

打开github,完成下图操作:

image-20220815182247315

image-20220815182404425

image-20220815182541297

五、使用TortoiseGit提交代码到远端仓库

在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹

image-20220815185026555

鼠标右键可以看到选项Git在这里创建版本库,点击创建版本库

image-20220815185825412

鼠标右键打开TortoiseGit->设置(Settings)->Git->远端(Remote),进行如下配置

image-20220815191405483

此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:

image-20220815190637369

我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:

1
+2
+3
+4
+5
+6
+7
+
正常的:绿色的对号 
+被修改过的:红色感叹号 
+新添加的:蓝色的加号
+未受控的(无版本控制的):蓝色的问号
+忽略不受控的:灰色的减号
+删除的:红色的x号 
+有冲突的:黄色的感叹号 
+

鼠标右键添加文件

image-20220815191829438

image-20220815191933736

image-20220815192002035

image-20220815192321480

image-20220815193032859

注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次

总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)

添加->提交->拉取->推送

那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 29, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab.jpg" new file mode 100644 index 000000000..d9cfb45c8 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_250x150_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ddd3ee0e Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.5390194acd038c6f1a1a71f213979cab_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.jpg" new file mode 100644 index 000000000..d9cfb45c8 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_120x120_fill_q75_box_smart1.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..867776495 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_1600x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..379f714b7 Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_1600x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_800x0_resize_q75_box.jpg" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..502784bfa Binary files /dev/null and "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_800x0_resize_q75_box.jpg" differ diff --git "a/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/index.html" "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/index.html" new file mode 100644 index 000000000..f77f1bde4 --- /dev/null +++ "b/p/git\347\211\210\346\234\254\346\216\247\345\210\266\345\234\250linux\347\273\210\347\253\257\346\230\276\347\244\272git\347\211\210\346\234\254\344\277\241\346\201\257/index.html" @@ -0,0 +1,57 @@ +【Git版本控制】在Linux终端显示Git版本信息 +
Featured image of post 【Git版本控制】在Linux终端显示Git版本信息

【Git版本控制】在Linux终端显示Git版本信息

如何在Git中显示当前分支

+
+

前言

在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑.bashrc文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。

步骤一:进入home目录

首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:

1
+
cd ~
+

步骤二:编辑.bashrc文件

接下来,我们需要编辑.bashrc文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:

1
+
vi .bashrc
+

步骤三:添加代码到文件末尾

在打开的.bashrc文件中,将以下代码添加到文件的末尾:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
function git_branch {  
+   branch="`git branch 2>/dev/null | grep "^\*" | sed -e "s/^\*\ //"`"  
+   if [ "${branch}" != "" ];then  
+       if [ "${branch}" = "(no branch)" ];then  
+           branch="(`git rev-parse --short HEAD`...)"  
+       fi  
+       echo " ($branch)"  
+   fi  
+}  
+
+export PS1='\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ '
+

这段代码定义了一个名为git_branch的函数,用于获取并显示当前Git分支的名称。然后,通过export命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。

步骤四:保存并退出vi编辑器

完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:

1
+
:wq
+

步骤五:执行命令使配置生效

最后,执行以下命令来使新的配置生效:

1
+
source ./.bashrc
+

现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。

通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!

+Licensed under CC BY-NC-SA 4.0
+Last updated on Oct 09, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover.jpg" "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover.jpg" new file mode 100644 index 000000000..804d36986 Binary files /dev/null and "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover.jpg" differ diff --git "a/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_120x120_fill_q75_box_smart1.jpg" "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..808659a63 Binary files /dev/null and "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_1600x0_resize_q75_box.jpg" "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..03c1dddf7 Binary files /dev/null and "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_1600x0_resize_q75_box.jpg" differ diff --git "a/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_800x0_resize_q75_box.jpg" "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c342e5a1d Binary files /dev/null and "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_800x0_resize_q75_box.jpg" differ diff --git "a/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/index.html" "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/index.html" new file mode 100644 index 000000000..555609cab --- /dev/null +++ "b/p/harmonyos\345\260\217\347\206\212\346\264\276\351\270\277\350\222\231\347\263\273\347\273\237\346\220\255\345\273\272/index.html" @@ -0,0 +1,116 @@ +【HarmonyOS】小熊派鸿蒙系统搭建 +
Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建

【HarmonyOS】小熊派鸿蒙系统搭建

BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。

+
+

一、BearPi-HM Micro 开发板介绍

BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。

二、Linux镜像下载

下载官方提供镜像(任选一种方式下载)

三、BearPi-HM Micro编译环境配置

在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置

1.首先添加如下镜像源

1
+
vi /etc/apt/source.list
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
# 添加中科大源
+deb https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
+deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse
+deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
+deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
+deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
+deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
+deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
+deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
+deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
+deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
+

2.更新镜像源

1
+
sudo apt-get update
+

3.安装依赖库及工具

1
+
sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi cpio device-tree-compiler net-tools openssh-server git vim openjdk-11-jre-headless
+

4.安装hb

1
+2
+
# 安装hb命令
+python3 -m pip install --user ohos-build==0.4.3
+
1
+2
+3
+4
+5
+6
+7
+8
+
# 环境变量配置
+sudo vim ~/.bashrc
+
+# 在.bashrc文件最后一行添加如下代码,并保存退出
+export PATH=~/.local/bin:$PATH
+
+# 更新环境变量
+source ~/.bashrc
+

5.测试hb是否安装成功

1
+
hb -h
+

image-20230407181805793

四、安装mkimage工具

首先解释这个工具的用途:用来制作不压缩或者压缩的多种可启动映象文件。

1.新建tools目录

1
+
mkdir ~/tools
+

2.下载mkimage.stm32工具到~/tools目录,并复制到/home/bearpi/tools/目录下

3.修改mkimage.stm32文件权限

1
+
chmod 777 ~/tools/mkimage.stm32
+

4.设置环境变量

1
+2
+3
+4
+5
+6
+7
+
vim ~/.bashrc
+
+# 将下面的代码拷贝至.bashrc文件最后,并保存退出
+export PATH=~/tools:$PATH
+
+# 更新环境变量
+source ~/.bashrc
+

五、bearpi镜像导入VMware

准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件->打开(O),选择我们Linux镜像中的BearPi-HM_Micro_Ubuntu.ovf文件,等待镜像文件的导入,开始登录

1
+2
+
账户:bearpi
+密码:bearpi
+

首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)->设置->网络适配器->NAT模式

此时打开一个终端,输入ifconfig查看ip

image-20230407185206621

六、源码获取

1
+2
+3
+4
+5
+
cd /home/bearpi
+
+mkdir project && cd project
+
+git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git
+

七、编译代码

首先进入到项目文件夹中

1
+
cd /home/bearpi/project/bearpi-hm_micro_small/
+

执行如下命令(普通用户模式终端下):

1
+
hb set
+

出现[OHOS INFO] Input code path: 提示信息后再输入.

image-20230407190200859

我们选择bearpi-hm_micro后回车

image-20230407190426957

输入下面的命令,等待下载程序完成

1
+
hb build -t notest --tee -f
+

当出现build success时,即代表编译成功

image-20230407191628183

八、查看编译出的固件位置

当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: /home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro 其中有以下文件是后面烧录系统需要使用的。

  • OHOS_Image.stm32:系统镜像文件
  • rootfs_vfat.img:根文件系统
  • userfs_vfat.img:用户文件系统

image-20230407191938678

我们将这三个文件复制到该目录下:/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/,方便后续烧录系统使用

1
+
cp -r OHOS_Image.stm32 rootfs_vfat.img userfs_vfat.img /home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/
+

image-20230407192926584

九、固件烧录

1.准备工作

2.连接开发板

首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:【Linux系统开发】Ubuntu配置SFTP服务

当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。

我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机

image-20230411183456029

3.镜像烧录

  • 首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。

  • 打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。

  • 点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv)。

  • 点击Browse按钮,然后选择工程源码下的烧录镜像路径

  • 点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机

image-20230411193521444

4.启动系统

将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。

3

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/index.html" new file mode 100644 index 000000000..7eca44d34 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221-x210\345\274\200\345\217\221\346\235\277-\350\231\232\346\213\237\351\251\261\345\212\250\345\210\233\345\273\272\346\265\201\347\250\213\351\251\261\345\212\250\347\274\226\350\257\221\350\277\233\345\206\205\346\240\270/index.html" @@ -0,0 +1,348 @@ +x210开发板 虚拟驱动创建流程 +
Featured image of post x210开发板 虚拟驱动创建流程

x210开发板 虚拟驱动创建流程

x210编写驱动编译进内核

+
+

内核编译常用命令

安装模块 +lsmod module_test.ko +创建设备文件 +mknod /dev/test c 250 0 +查看设备状态 +lsmod module_test.ko +查看设备注册信息(分为字符设备和块设备) +cat /proc/devices

知识补充:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
#include<stdio.h>
+int main(void)
+{
+	int i;
+	static int j;
+	printf(i);
+	printf(j);
+}
+// 注意:这里如果没有指定i值,则打印出来的是随机值
+// 如果定义一个静态变量而没有赋值,则打印默认为0
+

虚拟驱动创建流程

首先进入x210_bsp/kernel

make menuconfig

make -j4

cp arch/arm/boot/zImage /tftpboot/ -f

重启开发板查看开发板设备

ls /sys/devices/platform/

cd sys/class/leds

led_test_4编写完成后

编译不报错即可

cd /root/x210_bsp/kernel/drivers/leds/

cp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./

vi Makefile->

obj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o

vi Kconfig更改依赖(添加以下文件)

config LEDS_S5PV210 tristate "LED Support for S5PV210" help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.

进入到x210_bsp/kernel

执行make menuconfig

可以发现生成了新的配置(Device Drivers-> LED_Support),使能这个

执行make编译

cp arch/arm/boot/zImage /tftpboot/ -f

secureCRT:

cd sys/class/leds

进入LED1,执行

echo 1 > brightness // 灯亮

echo 0 > brightness //灯灭


最后附上源代码:

leds-s5pv210.c

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+
#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <mach/gpio-bank.h>
+#include <mach/regs-gpio.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <mach/gpio.h>
+#include <linux/leds.h>
+
+#define GPIO_LED1	S5PV210_GPJ0(3)
+#define GPIO_LED2	S5PV210_GPJ0(4)
+#define GPIO_LED3	S5PV210_GPJ0(5)
+
+#define X210_LED_OFF	1
+#define X210_LED_ON		0
+
+struct led_classdev mydev1;
+struct led_classdev mydev2;
+struct led_classdev mydev3;
+
+void s5pv210_led1_set(struct led_classdev *led_cdev,enum led_brightness value)
+{
+	printk(KERN_INFO "s5pv210_led1_set\n");
+	
+	if(value == LED_OFF)
+	{
+		gpio_set_value(GPIO_LED1,X210_LED_OFF);
+	}
+	else
+	{
+		gpio_set_value(GPIO_LED1,X210_LED_ON);
+	}
+}
+void s5pv210_led2_set(struct led_classdev *led_cdev,enum led_brightness value)
+{
+	printk(KERN_INFO "s5pv210_led2_set\n");
+	
+	if(value == LED_OFF)
+	{
+		gpio_set_value(GPIO_LED2,X210_LED_OFF);
+	}
+	else
+	{
+		gpio_set_value(GPIO_LED2,X210_LED_ON);
+	}
+}
+void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness value)
+{
+	printk(KERN_INFO "s5pv210_led3_set\n");
+	
+	if(value == LED_OFF)
+	{
+		gpio_set_value(GPIO_LED3,X210_LED_OFF);
+	}
+	else
+	{
+		gpio_set_value(GPIO_LED3,X210_LED_ON);
+	}
+}
+
+
+
+static  int __init s5pv210_led_init(void)
+{
+	int ret = -1;
+	// 申请GPIO
+	if(gpio_request(GPIO_LED1,"led1_gpj0.3"))
+	{
+		printk(KERN_ERR "gpio_request failed.\n");
+	}
+	else
+	{
+		gpio_direction_output(GPIO_LED1,1);
+	}
+	
+	mydev1.name = "led1";
+	mydev1.brightness = 0;
+	mydev1.brightness_set = s5pv210_led1_set;
+	
+	
+	ret = led_classdev_register(NULL,&mydev1);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "led_classdev_register failed.\n");
+		return ret;
+	}
+	
+	mydev2.name = "led2";
+	mydev2.brightness = 0;
+	mydev2.brightness_set = s5pv210_led2_set;
+	
+	
+	ret = led_classdev_register(NULL,&mydev2);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "led_classdev_register failed.\n");
+		return ret;
+	}
+	
+	mydev3.name = "led3";
+	mydev3.brightness = 0;
+	mydev3.brightness_set = s5pv210_led3_set;
+	
+	
+	ret = led_classdev_register(NULL,&mydev3);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "led_classdev_register failed.\n");
+		return ret;
+	}
+	
+	return 0;
+}
+
+static void __exit s5pv210_led_exit(void)
+{
+	led_classdev_unregister(&mydev1);
+	led_classdev_unregister(&mydev2);
+	led_classdev_unregister(&mydev3);
+	
+	gpio_free(GPIO_LED1);
+	gpio_free(GPIO_LED2);
+	gpio_free(GPIO_LED3);
+}
+
+module_init(s5pv210_led_init);
+module_exit(s5pv210_led_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("WYQ");
+MODULE_DESCRIPTION("module_test");
+

Makefile

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+
#KERN_VER = $(shell uname -r)
+#KERN_DIR = /lib/modules/$(KERN_VER)/build
+
+KERN_DIR = /root/x210_bsp/kernel
+
+obj-m += leds-s5pv210.o
+
+all:
+	make -C $(KERN_DIR) M=`pwd` modules
+
+.PHONY:clean
+clean:
+	make -C $(KERN_DIR) M=`pwd` modules clean
+
+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 22, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/index.html" new file mode 100644 index 000000000..efda63fc3 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ifconfig\344\270\215\346\230\276\347\244\272ip\345\234\260\345\235\200/index.html" @@ -0,0 +1,42 @@ +ifconfig不显示ip地址 +
Featured image of post ifconfig不显示ip地址

ifconfig不显示ip地址

ubuntu终端下命令ifconfig的问题解决

+
+

ubuntu终端下命令ifconfig的问题解决

问题一. ifconfig之后只显示lo,没有看到eth0 +问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 +问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。

问题一:ifconfig之后只显示lo,没有看到eth0 ?

1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 +ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback +这边的设置是本地回路。在后面加上

1
+2
+3
+4
+
iface eth0 inet static 
+address 192.168.1.230 //(ip地址) 
+netmask 255.255.255.0 //(子网掩码) 
+gateway 192.168.1.1 //(网关) 
+

其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。

2.eth0被关了 +输入命令行:ifconfig eth0 up #开启eth0


问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”?

1.先用sudo dhclient eth0更新IP地址 +2.然后运行sudo ifconfig eth0 +3.reboot


问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。

设置好后,如果直接ping www.baidu.com会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。

nameserver 8.8.8.8 
+nameserver 8.8.4.4 
+

这两个是Google提供的免费DNS服务器的IP地址

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 22, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86.jpg" new file mode 100644 index 000000000..a8a0eb2e9 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d9f4952a8 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.347615574b106862ffdb8fd26bc6de86_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.jpg" new file mode 100644 index 000000000..a8a0eb2e9 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..92e953898 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..8ccb05c9e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..b8b5c5342 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/index.html" new file mode 100644 index 000000000..e30ed1e36 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221linux\345\270\270\350\247\201\345\274\200\345\217\221\346\261\207\346\200\273/index.html" @@ -0,0 +1,124 @@ +【Linux系统开发】Linux常见开发汇总 +
Featured image of post 【Linux系统开发】Linux常见开发汇总

【Linux系统开发】Linux常见开发汇总

汇总一些常用的Linux问题解决方案(持续更新中...)

+
+

1.vmware tools 灰色无法点击

执行如下步骤:

1
+2
+3
+4
+5
+
sudo apt-get update
+
+sudo apt-get upgrade
+
+sudo apt-get install open-vm-tools-desktop -y
+

2.linux安装搜狗输入法

终端安装 fcitx

1
+
sudo apt-get install fcitx
+

到搜狗官方下载 deb 包:

使用linux自带的安装程序安装输入法后,安装如下输入法依赖:

1
+2
+
sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2
+sudo apt install libgsettings-qt1
+

重启即可

3.Cmake安装指定版本

首先去官网下载所需版本的压缩包:

执行解压命令

1
+
tar -zxv -f cmake-3.22.6.tar.gz
+

安装相关依赖:

1
+2
+3
+4
+5
+
sudo apt-get install g++
+
+sudo apt-get install libssl-dev
+
+sudo apt-get install make
+

进入解压后的cmake文件,执行:

1
+
./bootstrap
+

编译构建:

1
+
make
+

安装:

1
+
sudo make install
+

安装依赖项:

1
+
sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc
+

依次执行如下步骤:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+
# download source code
+git clone https://github.com/stlink-org/stlink
+cd stlink
+# build
+cmake .
+make
+# install
+cd bin
+sudo cp st-* /usr/local/bin
+cd ../lib
+sudo cp *.so* /lib32
+# add rules
+sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/
+sudo udevadm control --reload-rules
+sudo udevadm trigger
+

尝试烧录代码

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+
#check if st-link is plugged
+sudo st-info --probe
+
+# write hex
+sudo st-flash --format ihex write myapp.hex 
+
+# 一般下载一次,会失败,需要刷入两次;
+# write bin
+sudo st-flash write in.bin 0x8000000 #stm32f4xx
+
+# read bin
+st-flash read out.bin 0x8000000 0x1000
+
+# restart
+# 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作
+sudo st-flash reset
+

具体的GDB调试可以参考这篇文章:

+Licensed under CC BY-NC-SA 4.0
+Last updated on Oct 09, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..11d2d3a1d Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/index.html" new file mode 100644 index 000000000..a239d61da --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\210\251\347\224\250sd\350\277\220\350\241\214\346\265\201\346\260\264\347\201\257\347\250\213\345\272\217/index.html" @@ -0,0 +1,50 @@ +Study210利用SD运行流水灯程序 +
Featured image of post Study210利用SD运行流水灯程序

Study210利用SD运行流水灯程序

Study210利用SD运行流水灯程序

+
+

1.安装ecilpse

(1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包:

1
+2
+3
+4
+
eclipse-kepler-for-arm-windows-x86_32.7z 
+eclipse-kepler-for-arm-windows-x86_64.7z 
+eclipse-kepler-for-arm-gtk-linux-x86_64.7z 
+eclipse-kepler-for-arm-gtk-linux-x86_32.7z
+

选择自己需求对应的安装包下载解压即可(此处可点击下载

(2)配置好eclipse的环境变量

借鉴Eclipse环境变量配置-超详细

2.开始工程的创建

(1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace)

(2)建一个流水灯工程

首先在Project Explorer的空白栏右键单击->New->C Project +在这里插入图片描述 +项目名称填写LED_test +在这里插入图片描述 +点击next,finish

找到我们的项目工程示例,将全部文件复制到剪贴板 +在这里插入图片描述 +工程右键选择paste,选择粘贴全部 +在这里插入图片描述 +这是粘贴好的文件项目 +在这里插入图片描述 +工程右键Build Project或直接CTRL+B编译 +在这里插入图片描述 +此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 +在这里插入图片描述 +进入该目录下,可以发现生成了led.bin映像文件 +在这里插入图片描述

3.下载源码到SD卡

打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 +在这里插入图片描述

4.实例演示

(1)清除开发板中的bootloader

由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴【Linux系统开发】Study210开发板刷安卓系统)

(2)通过SD卡运行裸机程序

将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 +在这里插入图片描述

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 24, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..11d2d3a1d Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/index.html" new file mode 100644 index 000000000..7f15cc0cf --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221study210\345\274\200\345\217\221\346\235\277\345\210\267\345\256\211\345\215\223\347\263\273\347\273\237/index.html" @@ -0,0 +1,38 @@ +Study210开发板刷安卓系统 +
Featured image of post Study210开发板刷安卓系统

Study210开发板刷安卓系统

Study210开发板刷安卓系统

+
+

一、破坏BootLoader

1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)

在这里插入图片描述

2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)

3.输入root(password:123456)

4.然后输入busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync

5.回车后显示

1
+2
+
1+0 records in
+1+O records out
+

6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 +此时重新启动开发板就无法启动了

二、SD卡刷机(烧录uboot到SD卡中)

1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。

此处如果SD烧写不成功,可尝试用管理员身份运行。 +插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.

2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)

三、fastboot 下载安装镜像

1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。

2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wex7LBk8-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415202849623.png)\]

3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android

fastboot目录下应该包含的文件

在这里插入图片描述

Android中应该包含的文件(由于这里我烧写的是安卓系统)

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3DezB8H-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203108592.png)\]

4.进行内核和系统的烧写 ,具体代码如下:

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Dhso3IG-1650028395334)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203639928.png)\]

同时在SecureCRT下可以看到下载结果

5.最后在windows控制台下输入 fastboot reboot命令重启系统即可。

四、dnw 刷机(用fastboot刷Android )

  • 准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaxHZTvW-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415204109660.png)\]

注意:

(1)安装SecBulk.sys Njsmodi 2416 dnw drive的驱动程序在\X210V3S_A\tools\USB驱动\dnw_driver下,安装驱动需要禁用数字签名(可参考win10如何永久关闭数字签名)

(2)在使用dnw过程中需要长按电源键,否则会断开连接。

刷机步骤:

1.将拨码开关拨到USB启动位置。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rua1zZN3-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415205448252.png)\]

2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin

3.(同上操作)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin

注意!!!:下载的同时要看SecureCRT界面,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。

4.回到secureCRT

1
+2
+
输入fdisk -c 0 (进行分区)
+输入fastboot (查看分区)
+

5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:

+最后再输入

1
+
fastboot -w
+

全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。

在这里插入图片描述


此文章参考于S5PV210 Study210开发板刷系统

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 23, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..11d2d3a1d Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/index.html" new file mode 100644 index 000000000..c1381dcad --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu-\345\221\275\344\273\244\346\237\245\347\234\213\346\233\264\346\226\260\344\270\255/index.html" @@ -0,0 +1,38 @@ +Ubuntu命令查看手册 +
Featured image of post Ubuntu命令查看手册

Ubuntu命令查看手册

Ubuntu命令查看手册

+
+

进程管理类

1.top命令

  • top命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。
  • top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。

2.htop命令

  • htop命令是top的改进版。
  • 默认情况下,大多数Linux发行版本都没有安装htop。
  • htop命令显示的信息与top相同,但它的界面更人性化。

3.pstree

  • pstree命令也可以显示进程信息。
  • 它以树的形式显示进程。

4.kill

  • kill命令可以根据进程ID来杀死进程。
  • 你可以使用ps -A,top,或者grep命令获取到进程ID。
从技术层面来讲,kill命令可以发送任何信号给一个进程。
+你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。  
+

文件操作类(基础篇)

新建文件:touch
详细文档通过 man [command] 查看

管理文件

  • rm: 删除文件或目录(-r)
  • mkdir 新建目录
  • cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r)
  • mv 移动或重命名文件、目录

压缩tzip文件

  • zip FileName.zip DirName # 将DirName本身压缩
  • zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩

解压zip文件

  • unzip filename

查找含spark的目录、文件

  • find /home/jack -name ‘spark

更改密码

  • passwd

更改文件名或移动文件位置

  • 语句:mv oldFileName newFileName
  • 示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt

删除文件

  • 删除文件: rm test.txt
  • 删除空文件夹: rmdir test
  • 删除非空文件夹及其目录下的所有文件夹及文件:rm -r test
  • 删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt)

防火墙状态

首先需要输入安装命令: +apt install ufw

查看防火墙当前状态 +sudo ufw status

开启防火墙 +sudo ufw enable

关闭防火墙 +sudo ufw disable

查看防火墙版本 +sudo ufw version

默认允许外部访问本机 +sudo ufw default allow

默认拒绝外部访问主机 +sudo ufw default deny

允许外部访问443端口 +sudo ufw allow 443

拒绝外部访问443端口 +sudo ufw deny 443

允许某个IP地址访问本机所有端口 +sudo ufw allow from 192.168.0.1

网络设置

重置网卡 +sudo /etc/init.d/networking restart

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 25, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/index.html" new file mode 100644 index 000000000..586bef736 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\344\270\213\345\256\211\350\243\205\344\272\244\345\217\211\347\274\226\350\257\221\351\223\276/index.html" @@ -0,0 +1,89 @@ +ubuntu安装交叉编译工具链 +
Featured image of post ubuntu安装交叉编译工具链

ubuntu安装交叉编译工具链

ubuntu安装交叉编译工具链

+
+

ubuntu安装交叉编译工具链(附避坑指南)

1.打开Ubuntu,在终端进入/usr/local/目录下

cd /usr/local/
+

2.在local/目录下创建一个名为arm的文件夹

mkdir arm
+

3.在自己的共享文件夹下找到arm-2009q3.tar.bz2,并复制到之前创建的arm目录下

cp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/
+

4.进入到arm目录下,解压该其中文件

cd /usr/local/arm
+tar -jxvf arm-2009q3.tar.bz2	
+

5.然后执行:

cd arm-2009q3/bin
+./arm-none-linux-gnueabi-gcc -v
+

注意:这里如果输入./arm-none-linux-gnueabi-gcc -v终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持

sudo apt-get install libc6:i386
+

安装好了之后重新输入./arm-none-linux-gnueabi-gcc -v +在这里插入图片描述 +操作成功!

6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 +打开配置文件

sudo vim /etc/profile
+

7.在vi界面末尾处加入

export PATH=$PATH:/usr/local/arm/arm-2009q3/bin
+

8.回到主目录,查看交叉编译工具是否可用

cd ~
+source /etc/profile
+

这里如果没有出现相关信息,切换root用户再次输入命令

使用 echo $PATH查看交叉编译链的安装路径是否加入了环境变量。 +使用arm-linux-gnueabihf-gcc -v测试交叉编译链是否好使

9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:

chmod 777 mk-arm-linux-.sh
+./mk-arm-linux-.sh
+

这里由于运行时报错,原因详见解决linux的-bash: ./xx.sh: Permission denied

ls查看,可以发现符号链接出现,到此,交叉编译链配置成功!

在这里插入图片描述


附件:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line
+ln arm-none-linux-gnueabi-ar -s arm-linux-ar
+ln arm-none-linux-gnueabi-as -s arm-linux-as
+ln arm-none-linux-gnueabi-c++ -s arm-linux-c++
+ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt
+ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp
+ln arm-none-linux-gnueabi-g++ -s arm-linux-g++
+ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc
+ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1
+ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov
+ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb
+ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui
+ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof
+ln arm-none-linux-gnueabi-ld -s arm-linux-ld
+ln arm-none-linux-gnueabi-nm -s arm-linux-nm
+ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy
+ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump
+ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib
+ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf
+ln arm-none-linux-gnueabi-size -s arm-linux-size
+ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite
+ln arm-none-linux-gnueabi-strings -s arm-linux-strings
+ln arm-none-linux-gnueabi-strip -s arm-linux-strip
+

有问题欢迎评论留言致信:blogs

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 14, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756.jpg" new file mode 100644 index 000000000..549e381bd Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756_hud91d0899887ba9e32d396fd4ea2dabdc_982644_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756_hud91d0899887ba9e32d396fd4ea2dabdc_982644_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9a5c924e3 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.e62deebf6a072f2892f09288d8914756_hud91d0899887ba9e32d396fd4ea2dabdc_982644_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.jpg" new file mode 100644 index 000000000..549e381bd Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d201ed932 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..2f8a1d75f Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..776afa469 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/index.html" new file mode 100644 index 000000000..0333fb28e --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221ubuntu\351\205\215\347\275\256sftp\346\234\215\345\212\241/index.html" @@ -0,0 +1,72 @@ +【Linux系统开发】Ubuntu配置SFTP服务 +
Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务

【Linux系统开发】Ubuntu配置SFTP服务

SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。

+
+

SFTP介绍

SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)

安装步骤

1.目标:

在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。

2.查看Ubuntu系统信息

image-20230407101026858

3.检查是否已安装SFTP

在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:

image-20230407101132327

1
+2
+
安装openssh-client: sudo apt-get install openssh-client
+安装openssh-server: sudo apt-get install openssh-server
+

这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。

4.新建用户组SFTP-users,并新建用户SFTP

为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:

1
+2
+
sudo addgroup sftp-users
+sudo adduser sftp (这部分会让你新建用户组信息,建议最好截图保存下)
+

5.给SFTP赋权并新建用户组SSH-users

将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:

1
+
sudo usermod -G sftp-users -s /bin/false sftp
+

创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。

1
+2
+
sudo addgroup ssh-users
+sudo usermod -a -G ssh-users bbc2005
+

6.创建并设置SFTP用户目录

为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。

1
+2
+3
+4
+5
+
sudo mkdir /home/sftp_root
+sudo mkdir /home/sftp_root/shared
+sudo chown yifang:sftp-users /home/sftp_root/shared
+
+sudo chmod 770 /home/sftp_root/shared
+

7.修改SSH配置文件

在sshd_config文件的最后添加以下内容:

1
+
vi /etc/ssh/sshd_config 
+
1
+2
+3
+4
+5
+6
+7
+
AllowGroups ssh-users sftp-users  
+Match Group sftp-users  
+ChrootDirectory /home/sftp_root  
+AllowTcpForwarding no  
+X11Forwarding no  
+
+ForceCommand internal-sftp
+

这些内容的意思是:

  • 只允许ssh-users和SFTP-users通过SSH访问系统;
  • 针对SFTP-users用户,增加一些额外的设置:
    • 将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);
    • 禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。
    • 如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。

8.SFTP客户端验证

首先将虚拟机重启:

1
+
sudo reboot
+

在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。

查看ubuntu网络ip地址

1
+
ifconfig
+

image-20230407103802472zhe

这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考RaiDrive—将网盘映射为磁盘

image-20230407104441660

此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。

image-20230407104643007

+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 07, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..11d2d3a1d Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.2811961847a4d0296a2c6b9cb3709bc7_hu1f665307cfc2974f92d9a28bfa39459d_48351_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/index.html" new file mode 100644 index 000000000..2226953b8 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221x210\345\274\200\345\217\221\346\235\277\346\240\271\347\233\256\345\275\225\346\226\207\344\273\266\347\263\273\347\273\237\346\236\204\345\273\272/index.html" @@ -0,0 +1,221 @@ +x210开发板根目录文件系统构建 +
Featured image of post x210开发板根目录文件系统构建

x210开发板根目录文件系统构建

x210开发板根目录文件系统构建

+
+

一、开发板配置

(使用secureCRT) +首先确保开发板完成以下配置:

主机IP: +set ipaddr192.168.1.10 +服务器IP: +set serverip 192.168.1.141 +网关: +set gatewayip 192.168.1.1 +子网掩码: +set netmask 255.255.255.0 +内核驱动设置: +set bootcmd 'tftp 30008000 zImage; bootm 30008000' +bootargs配置: +set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200

最后输入save保存一下,这样开发板的网络和内核配置就设置好了

二、了解rootfs

rootfs的两种表现形式: +1、nfs方式启动的文件夹形式的rootfs(主机)

2、用来烧录的镜像形式rootfs(开发板)

三、虚拟机文件配置

1.目录配置

首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: +rootfs x210_bsp

这时候我们需要知道这两个文件夹下有什么:

  • x210_bsp:用于uboot烧录和配置
  • rootfs:用于挂载开发板根文件系统

2.x210_bsp配置

首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压

以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用

3.rootfs配置

首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压

以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件

4.make menuconfig

进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单

这里我们按下面操作完成网络配置

1
+2
+
[*]Networking support --->
+	Networking options --->
+

网络文件系统设置

1
+2
+
File systems --->
+	[*]Networking File Systems --->
+

有需要把开发板作为服务器端的也可以选择把NFS server support设置打开,这里我们仅实验客户端

以上配置结束后输入命令make编译,至此开发板uboot的网络和文件系统部分配置结束。

四、busybox的移植实战

1、了解busybox

busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。

2、busybox源码获取

busybox官网

注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)

3、busybox配置

(1)修改Makefile

首先进入~/rootfs/x210_rootfs/busybox-1.24.1目录下

输入命令vi Makefile进入脚本进行以下修改

173行:CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi- +注意:此处的交叉编译链需要对照自己电脑的交叉编译链 +191行:ARCH=arm

(2)make menuconfig配置

Tip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 +因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。

make menuconfig

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
Busybox Settings--->
+	Build Options--->
+		[*]Build BusyBox as a static binary(no shared libs)
+
+		
+Busybox Library Tuning--->
+	[*]vi-style line editing commands
+	[*]Fancy shell prompts
+	
+	
+Linux Module Utilities--->
+	[ ]Simplified modutils
+	[*]insmod
+	[*]rmmod
+	[*]lsmod
+	[*]modprobe
+	[*]depmod
+
+	
+Linux System Utilities--->[*]mdev
+	[*]Support /etc/mdev.conf
+	[*]Support subdirs/symlinks
+	[*]Support regular expressions substitutions when renaming dev
+	[*]Support command execution at device addition/removal
+	[*]Support loading of firmwares
+

大家学习使用的时候跟着上面的进行配置即可 +配置完成后,输入以下命令: +make -j4 (4代表我主机的内核数) +无报错继续下一步: +make install

解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装

(3)设置busybox安装路径

  • make menuconfig
1
+2
+3
+
Busybox Settings --->
+	Installation Options ("make install" behavior) --->
+		(./)BusyBox installation prefix) //这里设置安装路径
+

(4)解决方案 +在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。

make -j4编译可能遇到的问题:

  • sync.c(text.sync_main+0x78):undefined reference to 'syncfs'

分析:可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。

解决方法:

make menuconfig +点击/进入搜索,输入SYNC,根据提示禁用SYNC +最后再make -j4编译一下即可

+在这里插入图片描述

其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。

(5)make install简述

  • 默认安装位置:./_install
  • 文件包含有:bin linuxrc sbin usr

ls -l可以看到: linuxrc -> bin/busybox //这个linuxrc其实就是个符号链接

这里也不难发现,bin下的所有的符号链接都指向了busybox

(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下

1
+2
+3
+4
+
make menuconfig 
+	Busybox Settings —> 
+		Installation Options (“make install” behavior) —> 
+			(/root/rootfs/x210_rootfs)BusyBox installation prefix
+

执行make install后,回到被挂载的目录下,可以发现这四个文件已经生成。

五、NFS挂载根文件系统

1.NFS简述

  • NFS 是Network File System的缩写,即网络文件系统。
  • 功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。

2.NFS服务器安装

sudo apt-get install nfs-kernel-server

3.NFS使用过程

启动NFS服务器->启动NFS客户端->挂载NFS目录

4.NFS配置

  • 输入命令vim /etc/exports

在最后一行修改

  • "文件挂载目录" *(rw,sync,no_root_squash,no_subtree_check)

  • 保存退出后,输入mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs(根据实际情况修改)

  • 输入命令/etc/init.d/nfs-kernel-server restart重启NFS服务

六、开发板根目录配置

首先将etc目录放置到挂载根目录下

etc目录下载:

点击此处

1.inittab文件详解

<1>添加一个典型的inittab文件到etc目录下

inittab下载

<2>inittab格式解析

id:runlevels:action:process

在这里插入图片描述

解释:

  • id:标识符,即代表记录的名字
  • runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别

  • action:用于描述该级别该执行什么操作(部分说明)

  • process:具体执行的命令

<3>了解busybox init与inittab之间的关系

  • busybox init进程主要完成系统的初始化工作。

busybox init进程的工作流程:

为init设置信号处理过程->初始化控制台->剖析/etc/inittab文件->执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS->执行所有导致 init 暂停的 inittab 命令(动作类型: wait)->执行所有仅执行一次的 inittab(动作类型: once)

  • 一旦完成以上工作, init 进程便会循环执行以下进程:

<1>执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) +<2>执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)

  • 简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。

注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。

<4>配置 +vi命令打开inittab模板文件

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
#first:run the system script file   注释
+::sysinit:/etc/init.d/rcS    //在控制台初始化之前执行rcS
+
+::askfirst:-/bin/sh
+
+::ctrlaltdel:-/sbin/reboot  //执行控制台时的打印信息
+
+#umount all filesystem  //同时按住3键可以重启
+::shutdown:/bin/umount -a -r//关机时接触挂载init
+
+#restart init process//重启时启动
+::restart:/sbin/init
+

修改脚本: +在这里插入图片描述

2.rcS文件详解

<1>添加一个典型的rcS文件到etc目录下

rcS下载

<2>rcS文件解析

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
#!/bin/sh   需要继续添加环境变量,在后面:/new 即可
+PATH=/sbin:/bin:/usr/sbin:/usr/bin 
+
+runlevel=S
+prevlevel=N
+
+umask 022
+
+export PATH runlevel prevlevel
+
+mount -a
+
  • PATH=xxx

PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。

  • runlevel=

linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启

  • umask=

umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。

  • mount -a

mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)

3.rcS实战

首先将前面提供的etc压缩包模板下载至共享文件夹

<1>输入命令打开rcS脚本:vi etc/init.d/rcS。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了

<2>mdev

udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。

rcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在rcS文件中添加以下与mdev有关的2行配置项后:

1
+2
+
echo /sbin/mdev > /proc/sys/kernel/hotplug
+mdev -s
+

在这里插入图片描述

再次启动系统后发现/dev目录下生成了很多的设备驱动文件

<3>hostname

我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名

hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。

  • 添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname

<4>ifconfig

(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40

在这里插入图片描述

<5>mount挂载测试

这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如

1
+2
+3
+4
+
mount: mounting tmpfs on /var failed: No such file or directory
+mount: mounting tmpfs on /tmp failed: No such file or directory
+mount: mounting tmpfs on /dev failed: No such file or directory
+......
+

这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,输入mkdir命令在根目录依次创建即可

七、动态链接库的拷贝

1.静态编译链接测试

首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件

1
+2
+3
+4
+5
+6
+7
+8
+
a.c file->
+
+#include<stdio.h>
+int main()
+{
+	printf("hello world!\n");
+	return 0;
+}
+

2.解决办法:

拷贝一份动态链接库文件到开发板根目录下

1
+
cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf
+

3.解释:

这时候执行命令./a.out发现可以正常打印

4.strip工具

动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在传统的嵌入式系统中flash空间是有限的,为了节省空间常常把这些符号信息去掉。这样节省空间并且不影响运行。

去掉符号信息的命令:

arm-linux-strip *so*

八、ext2格式镜像烧录

1. 确定文件夹格式的rootfs可用

前面我们已经提前配置好,此处不再赘述

2.ext2镜像制作

  • 首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。

  • 然后输入以下命令:

1
+2
+3
+4
+5
+6
+7
+
dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
+
+losetup  /dev/loop1 rootfs.ext2
+
+mke2fs -m 0 /dev/loop1 10240
+
+mount -t ext2 /dev/loop1 ./ext2_rootfs/
+
  • 此时我们复制一份开发板根目录到ext2_rootfs下
1
+
cp rootfs.ext2 /mnt/hgfs/Myshare/ -f
+
  • 进入~/rootfs目录,执行清除卸载命令
1
+2
+
umount /dev/loop1
+losetup -d /dev/loop1
+

至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!


参考资料:

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 28, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover.jpg" new file mode 100644 index 000000000..5e0a7aa05 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..60b2c6b62 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..3672f81d1 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..dac155031 Binary files /dev/null and "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" differ diff --git "a/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/index.html" "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..24e7f6c60 --- /dev/null +++ "b/p/linux\347\263\273\347\273\237\345\274\200\345\217\221\345\244\232\347\272\277\347\250\213\346\212\200\346\234\257\345\255\246\344\271\240/index.html" @@ -0,0 +1,475 @@ +多线程技术学习(基于Linux) +
Featured image of post 多线程技术学习(基于Linux)

多线程技术学习(基于Linux)

Linux多线程概念、inux线程实现、线程同步的方法、线程的互斥、互斥PK信号量、信号量操作、互斥操作、条件变量

+
+

1.Linux多线程概念

(1)线程:指运行中的程序的调度单位。

(2)多线程的优点:

  • 运行与一个线程中的多个线程,他们彼此之间使用相同的地址空间共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。
  • 进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式
  • 应用程序响应速度提高
  • 使多CPU系统更加高效
  • 改善程序结构

(3)线程的生命周期

就绪->运行->阻塞->终止


2.linux线程实现

(1)线程创建

  • 头文件包含 +#include <pthread.h>

  • 定义函数:

      int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg)
    +
  • 函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数
    arg: start_rtn的参数

(2)线程退出

  • 头文件包含: +#include <pthread.h>
  • 定义函数: +void pthread_exit(void * rval_ptr)
  • 功能:终止调用线程Rval_ptr:线程退出返回值的指针。

(3)线程等待

  • 头文件包含: +#include <pthread.h>

  • 定义函数:

      int pthread_join(pthread_t tid,void **rval_ptr)
    +
  • 功能:阻塞调用线程,直到指定的线程终止。

  • 函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针

(4)线程标识获取

  • 头文件包含: +#include <pthread.h>
  • 定义函数: +pthread_t pthread_self(void)
  • 功能:获取调用线程的 thread identifier

(5)线程清除

  • 头文件包含: +#include <pthread.h>

  • 定义函数:

      void pthread_cleanup_push(void (*rtn)(void *),void *arg)
    +
  • 功能:将清除函数压入清除栈

  • 函数说明: +Rtn:清除函数 +Arg:清除函数的参数


3.线程同步的方法

进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:

互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions


4.线程的互斥

线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。

(1)创建

在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:

  • 对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER
  • 对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。

函数使用: +头文件: +#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr)
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+

(2)加锁

对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。

函数使用:

int pthread_mutex_lock(pthread_mutex_t *mutex)
+int pthread_mutex_trylock(pthread_mutex_t *mutex)
+

返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。

(3)解锁

在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。

int pthread_mutex_unlock(pthread_mutex_t *mutex)
+

5.互斥PK信号量

Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:

  1. mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放
  2. 初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。

6.信号量操作(代码演示)

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+
#include<stdio.h>
+#include<string.h>
+#include<pthread.h>
+#include<stdlib.h>
+#include<semaphore.h>
+
+//子线程处理
+
+char buf[200];
+sem_t sem;
+int flag;
+
+void *func(void *arg)
+{
+	sem_wait(&sem); // 接收信号量
+	/*
+	Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。
+	如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。
+	*/
+	//while(strncmp(buf,"end",3) != 0)
+	while(flag == 0)
+	{
+		printf("input %d char.\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+	}
+	
+	pthread_exit(NULL);
+}
+
+int main(void)
+{
+	int ret = -1;
+	pthread_t th = -1;
+	
+	sem_init(&sem,0,0); // 在sem指向的地址处初始化未命名的信号量
+	
+	ret = pthread_create(&th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0
+	if(ret != 0)
+	{
+		printf("pthread_create error.\n");
+		return -1;
+	}
+	
+	printf("please input string,end with Enter.\n");
+	while(scanf("%s",buf))
+	{
+		if(!strncmp(buf,"end",3))
+		{
+			printf("process end\n");
+			flag = 1;
+			sem_post(&sem); //增加(解锁)sem指向的信号量
+			break;
+		}
+		
+		printf("input %d char .\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+	}
+	
+	printf("wait reclaim child thread.\n");
+	ret = pthread_join(th,NULL);
+	if(ret != 0)
+	{
+		printf("pthread_join error.\n");
+		exit(-1);
+	}
+	printf("reclaim child thread successfully.\n");
+	
+	return 0;
+}
+

7.互斥操作(函数演示)

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+
#include<stdio.h>
+#include<string.h>
+#include<pthread.h>
+#include<stdlib.h>
+
+//子线程处理
+
+char buf[200];
+pthread_mutex_t mutex;
+int flag;
+
+void *func(void *arg)
+{
+	sleep(1);
+	while(flag == 0)
+	{ 
+		pthread_mutex_lock(&mutex);// 互斥加锁
+		printf("input %d char.\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+		pthread_mutex_unlock(&mutex); // 解锁
+	}
+	
+	pthread_exit(NULL);
+}
+
+int main(void)
+{
+	int ret = -1;
+	pthread_t th = -1;
+	
+	pthread_mutex_init(&mutex,NULL);
+	
+	ret = pthread_create(&th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0
+	if(ret != 0)
+	{
+		printf("pthread_create error.\n");
+		return -1;
+	}
+	
+	printf("please input string,end with Enter.\n");
+	while(1)
+	{
+		pthread_mutex_lock(&mutex);// 对互斥对象加锁锁定
+		scanf("%s",buf);
+		pthread_mutex_unlock(&mutex); // 输入后解锁
+		if(!strncmp(buf,"end",3))
+		{
+			printf("process end\n");
+			flag = 1;
+			break;
+		}
+		
+		printf("input %d char .\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+	}
+	
+	printf("wait reclaim child thread.\n");
+	ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。
+	if(ret != 0)
+	{
+		printf("pthread_join error.\n");
+		exit(-1);
+	}
+	printf("reclaim child thread successfully.\n");
+	pthread_mutex_destroy(&mutex);
+	
+	
+	return 0;
+}
+

8.条件变量(代码演示)

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
#include<stdio.h>
+#include<string.h>
+#include<pthread.h>
+#include<stdlib.h>
+
+//子线程处理
+
+char buf[200];
+pthread_mutex_t mutex;
+pthread_cond_t cond;
+int flag;
+
+void *func(void *arg)
+{
+	while(flag == 0)
+	{ 
+		pthread_mutex_lock(&mutex);// 互斥加锁
+		pthread_cond_wait(&cond,NULL);// 线程同步等待
+		printf("input %d char.\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+		pthread_mutex_unlock(&mutex); // 解锁
+	}
+	
+	pthread_exit(NULL);
+}
+
+int main(void)
+{
+	int ret = -1;
+	pthread_t th = -1;
+	
+	pthread_mutex_init(&mutex,NULL);
+	pthread_cond_init(&cond,NULL); //初始化条件变量
+	
+	ret = pthread_create(&th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0
+	if(ret != 0)
+	{
+		printf("pthread_create error.\n");
+		return -1;
+	}
+	
+	printf("please input string,end with Enter.\n");
+	while(1)
+	{
+		
+		scanf("%s",buf);
+		pthread_cond_signal(&cond);// 发送信号
+		if(!strncmp(buf,"end",3))
+		{
+			printf("process end\n");
+			flag = 1;
+			break;
+		}
+		
+		printf("input %d char .\n",strlen(buf));
+		memset(buf,0,sizeof(buf));
+	}
+	
+	printf("wait reclaim child thread.\n");
+	ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。
+	if(ret != 0)
+	{
+		printf("pthread_join error.\n");
+		exit(-1);
+	}
+	printf("reclaim child thread successfully.\n");
+	pthread_mutex_destroy(&mutex);
+	pthread_cond_destroy(&cond);// 条件变量销毁
+	
+	
+	return 0;
+}
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05.jpg" new file mode 100644 index 000000000..bcee513d0 Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05_hu469f982a08585212a410fea8179642b3_154073_250x150_fill_q75_box_smart1.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05_hu469f982a08585212a410fea8179642b3_154073_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d41b4ea66 Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.cb159d630b796ad06ddd953bc8f78f05_hu469f982a08585212a410fea8179642b3_154073_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.jpg" new file mode 100644 index 000000000..bcee513d0 Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_120x120_fill_q75_box_smart1.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..74ab2db9b Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_1600x0_resize_q75_box.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..044ed3f8f Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_800x0_resize_q75_box.jpg" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..4520ba3aa Binary files /dev/null and "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/cover_hu469f982a08585212a410fea8179642b3_154073_800x0_resize_q75_box.jpg" differ diff --git "a/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/index.html" "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/index.html" new file mode 100644 index 000000000..081b512df --- /dev/null +++ "b/p/matterchip\350\256\276\345\244\207\345\261\202\350\256\276\350\256\241\347\254\224\350\256\260/index.html" @@ -0,0 +1,542 @@ +【Matter】CHIP设备层设计笔记 +
Featured image of post 【Matter】CHIP设备层设计笔记

【Matter】CHIP设备层设计笔记

本文档包含与 CHIP 设备层 ( `src/platform`) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方。

+
+

CHIP设备层设计笔记

本文档包含与 CHIP 设备层 ( src/platform) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。

这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。

本文档包含以下部分:


设备层适配模式

设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。

CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。

作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。

为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。

尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。

以下各节描述了用于实现这些目标的一些模式。

  1. 接口和实现类
  2. 方法转发
  3. 目标平台选择
  4. 通用实现类
  5. 覆盖通用行为
  6. 通用实现的多重继承和子类化
  7. 通用实现行为的静态虚拟化
  8. .cpp 文件和显式模板实例化

接口和实现类

CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。

外部可见的抽象接口类定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。

实现提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。

设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。

抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀Impl。在所有情况下,实现类都需要从其接口类公开继承。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
class ConfigurationManagerImpl;
+
+/** Interface class for ConfigurationManager component
+ */
+class ConfigurationManager
+{
+    using ImplClass = ConfigurationManagerImpl;
+
+public:
+    CHIP_ERROR GetDeviceId(uint64_t & deviceId);
+    static CHIP_ERROR Init();
+    ...
+};
+
+/** Concrete implementation of ConfigurationManager component for a specific platform
+ */
+class ConfigurationManagerImpl final
+    : public ConfigurationManager
+{
+    ...
+};
+

方法转发

接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。this这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ 奇怪的重复模板模式 ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,ImplClass使转发方法定义更加简洁。

1
+2
+3
+4
+5
+
inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t & deviceId)
+{
+    /* forward method call... */
+    return static_cast<ImplClass*>(this)->_GetDeviceId(deviceId);
+}
+

该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:

1
+2
+3
+4
+
inline CHIP_ERROR ConfigurationManager::Init()
+{
+    return ImplClass::_Init();
+}
+

作为转发方法目标的实现类上的方法称为*实现方法*。每一种转发方法都必须有相应的实现方法。

前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。

实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
class ConfigurationManagerImpl;
+
+/** Interface class for ConfigurationManager component
+ */
+class ConfigurationManager
+{
+    using ImplClass = ConfigurationManagerImpl;
+
+public:
+    CHIP_ERROR GetDeviceId(uint64_t & deviceId);
+    static CHIP_ERROR Init();
+    ...
+};
+
+/** Concrete implementation of ConfigurationManager component for specific platform
+ */
+class ConfigurationManagerImpl final : public ConfigurationManager
+{
+    /* Let the forwarding methods on ConfigurationManager call implementation
+       methods on this class. */
+    friend ConfigurationManager;
+
+private:
+    CHIP_ERROR _GetDeviceId(uint64_t & deviceId);
+    static CHIP_ERROR _Init();
+    ...
+};
+
+inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t & deviceId)
+{
+    /* Forward calls to corresponding implementation method... */
+    return static_cast<ImplClass*>(this)->_GetDeviceId(deviceId);
+}
+
+inline CHIP_ERROR ConfigurationManager::Init()
+{
+    /* Forward calls to corresponding static implementation method... */
+    return ImplClass::_Init();
+}
+

目标平台选择

实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:

1
+2
+3
+4
+5
+6
+7
+8
+9
+
/* contents of ConfigurationManager.h */
+
+...
+
+#define CONFIGURATIONMANAGERIMPL_HEADER \
+        <platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h>
+#include CONFIGURATIONMANAGERIMPL_HEADER
+
+...
+

该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。

每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如ESP32)。所有此类文件都具有相同的文件名(例如ConfigurationManagerImpl.h),并且每个文件都包含类似名称的类的定义(ConfigurationManagerImpl)。

特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 src/adaptations/device-layer/ESP32)。与特定于平台的头目录一样,这些子目录以目标平台命名。

设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 --device-layer=<target-platform>。传递 –device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:

1
+2
+
#define CHIP_DEVICE_LAYER_TARGET ESP32
+#define CHIP_DEVICE_LAYER_TARGET_ESP32 1
+

–device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。

通用实现类

通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。

为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。

通用实现基类被实现为遵循 C++ 奇怪重复模板模式的C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+
/** Generic base class for use in implementing ConfigurationManager components
+ */
+template<class ImplClass>
+class GenericConfigurationManagerImpl
+{
+    ...
+};
+
+/** Concrete implementation of ConfigurationManager component for specific platform
+ */
+class ConfigurationManagerImpl final
+    : public ConfigurationManager,
+      public GenericConfigurationManagerImpl<ConfigurationManagerImpl> /* <-- Implementation provided by
+                                                                              generic base class. */
+{
+    ...
+};
+

在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+
/** Interface class for ConfigurationManager component
+ */
+class ConfigurationManager
+{
+    using ImplClass = ConfigurationManagerImpl;
+
+public:
+    CHIP_ERROR GetDeviceId(uint64_t & deviceId);
+    static CHIP_ERROR Init();
+    ...
+};
+
+/** Generic base class for use in implementing ConfigurationManager components
+ */
+template<class ImplClass>
+class GenericConfigurationManagerImpl
+{
+protected:
+    CHIP_ERROR _GetDeviceId(uint64_t & deviceId); /* <-- Invoked when GetDeviceId() called. */
+    ...
+};
+
+/** Concrete implementation of ConfigurationManager component for specific platform
+ */
+class ConfigurationManagerImpl final
+    : public ConfigurationManager,
+      public GenericConfigurationManagerImpl<ConfigurationManagerImpl>
+{
+    ...
+};
+

覆盖通用行为

如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。

新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t & deviceId)
+{
+    using GenericImpl = GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
+
+    /* Call the generic implementation to get the device id. */
+    uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId);
+
+    /* Special case the situation where the device id is not known. */
+    if (deviceId == kNodeIdNotSpecified) {
+        deviceId = PLATFORM_DEFAULT_DEVICE_ID;
+    }
+
+    return deviceId;
+}
+

通用实现的多重继承和子类化

具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。

1
+2
+3
+4
+5
+6
+7
+8
+9
+
/** Concrete implementation of ConfigurationManager component for specific platform
+ */
+class ConfigurationManagerImpl final
+    : public ConfigurationManager,
+      public GenericWiFiConfigurationManagerImpl<ConfigurationManagerImpl>, /* <-- WiFi features */
+      public GenericThreadConfigurationManagerImpl<ConfigurationManagerImpl> /* <-- Thread features */
+{
+    ...
+};
+

通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
/** Generic base class for use in implementing PlatformManager features
+ *  on all platforms.
+ */
+template<class ImplClass>
+class GenericPlatformManagerImpl
+{
+    ...
+};
+
+/** Generic base class for use in implementing PlatformManager features
+ *  on FreeRTOS platforms.
+ */
+template<class ImplClass>
+class GenericPlatformManagerImpl_FreeRTOS
+    : public GenericPlatformManagerImpl<ImplClass>
+{
+    ...
+};
+

通用实现行为的静态虚拟化

在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。

例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过GetDeviceId()从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。

this遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数Impl()有助于使代码简洁。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+
template<class ImplClass>
+class GenericConfigurationManagerImpl
+{
+protected:
+    CHIP_ERROR _GetDeviceId(uint64_t & deviceId);
+    ...
+private:
+    ImplClass * Impl() { return static_cast<ImplClass*>(this); }
+};
+
+class ConfigurationManagerImpl final
+    : public ConfigurationManager,
+      public GenericConfigurationManagerImpl<ConfigurationManagerImpl>
+{
+    friend GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
+private:
+    CHIP_ERROR ReadConfigValue(const char * key, uint64_t & value);
+};
+
+template<class ImplClass>
+CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
+{
+    /* delegate to the implementation class to read the 'device-id' config value */
+    return Impl()->ReadConfigValue(device-id, deviceId);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(const char * key, uint64_t & value)
+{
+    /* read value from platform-specific key-value store */
+    ...
+}
+

在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。

同样,委托是通过转换this指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+
template<class ImplClass>
+class GenericPlatformManagerImpl
+{
+protected:
+    void _DispatchEvent(const CHIPDeviceEvent * event);
+    void DispatchEventToApplication(const CHIPDeviceEvent * event);
+    ...
+private:
+    ImplClass * Impl() { return static_cast<ImplClass*>(this); }
+};
+
+template<class ImplClass>
+void GenericPlatformManagerImpl<ImplClass>::_DispatchEvent(const CHIPDeviceEvent * event)
+{
+    ...
+    /* Delegate work to method that can be overridden by implementation class */
+    Impl()->DispatchEventToApplication(event);
+    ...
+}
+
+template<class ImplClass>
+void GenericPlatformManagerImpl<ImplClass>::DispatchEventToApplication(const CHIPDeviceEvent * event)
+{
+    /* provide default implementation of DispatchEventToApplication() */
+    ...
+}
+

.cpp 文件和显式模板实例化

C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。

为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀.cpp。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。

1
+2
+3
+4
+5
+6
+7
+8
+9
+
/* contents of GenericConfigurationManagerImpl.h */
+
+template<class ImplClass>
+class GenericConfigurationManagerImpl
+{
+protected:
+    CHIP_ERROR _GetDeviceId(uint64_t & deviceId);
+    ...
+};
+
1
+2
+3
+4
+5
+6
+7
+
/* contents of GenericConfigurationManagerImpl.cpp */
+
+template<class ImplClass>
+CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
+{
+    ...
+}
+

通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。为了避免这种情况,设备层使用显式模板实例化的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件extern template class在使用模板类之前都包含一个声明。这告诉编译器不要在该上下文中实例化模板。

1
+2
+3
+4
+5
+6
+7
+8
+9
+
/* contents of ConfigurationManagerImpl.h */
+
+#include <CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h>
+
+// Instruct the compiler to instantiate the GenericConfigurationManagerImpl<ConfigurationManagerImpl>
+// class only when explicitly asked to do so.
+extern template class GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
+
+...
+

然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并template class使用定义来强制显式实例化模板。

1
+2
+3
+4
+5
+6
+7
+8
+
/* contents of ConfigurationManagerImpl.cpp */
+
+#include <CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp>
+
+// Fully instantiate the GenericConfigurationManagerImpl<ConfigurationManagerImpl> class.
+template class GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
+
+...
+

结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Aug 20, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5.jpg" new file mode 100644 index 000000000..d05651882 Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5_huabdcd8d32271ef5f0289704c9f451cf6_220565_250x150_fill_q75_box_smart1.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5_huabdcd8d32271ef5f0289704c9f451cf6_220565_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..69b93e7c4 Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.59e117b6b6cbca435fc9f8d3dfac39e5_huabdcd8d32271ef5f0289704c9f451cf6_220565_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" new file mode 100644 index 000000000..d05651882 Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_120x120_fill_q75_box_smart1.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..765215c8d Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_1600x0_resize_q75_box.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..b704676d3 Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_800x0_resize_q75_box.jpg" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9630c79f6 Binary files /dev/null and "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_800x0_resize_q75_box.jpg" differ diff --git "a/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" new file mode 100644 index 000000000..4d96771ab --- /dev/null +++ "b/p/matteresp-matter\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" @@ -0,0 +1,278 @@ +【Matter】esp-matter开发环境搭建 +
Featured image of post 【Matter】esp-matter开发环境搭建

【Matter】esp-matter开发环境搭建

Matter 作为一个应用级的协议,向下屏蔽了设备制造商的生态和系统,让各种智能家居设备之间能相互通信。

+
+

esp-matter开发环境搭建


前提准备

1.Ubuntu22.04(磁盘容量不小于80G)

2.科学上网环境

由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。

参考链接:【经验分享】Linux 环境下v2ray的使用

esp-idf 开发环境搭建

1.ESP-IDF 依赖环境安装

参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html

1
+
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
+

由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:

  • Problem1:执行 git submodule 速度慢
  • Problem2:执行install.sh 速度慢

所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。

2.Problem1 solution

首先使用递归克隆命令克隆整个仓库到文件夹下

1
+2
+3
+4
+5
+
mkdir /home/kurisaw/Desktop/esp
+
+git clone --recursive https://github.com/espressif/esp-idf.git
+
+git submodule update --init --recursive
+

由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:

  • jihu-mirror 使用(推荐)
  • submodule-update 使用(不推荐)

2.1 jihu-mirror 使用(推荐)

  • Step 1:
1
+2
+
git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git
+cd esp-gitee-tools
+
  • Step 2:
1
+2
+3
+
// 使用如下命令将仓库的 URL 进行替换:
+
+git config --global url.https://jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf
+

当我们使用命令 git clone https://github.com/espressif/esp-idf 时,默认的 URL https://github.com/espressif/esp-idf 将被自动替换成 https://jihulab.com/esp-mirror/espressif/esp-idf

  • Step 3:
1
+2
+3
+
// 启用镜像URL
+
+./jihu-mirror.sh set
+

使用命令 ./jihu-mirror.sh unset 恢复,不使用镜像的 URL。

  • Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库
1
+
git clone --recursive https://github.com/espressif/esp-idf.git
+

当然如果不想使用镜像的URL可以使用如下命令进行恢复:

1
+
./jihu-mirror.sh unset
+

2.2 submodule-update 使用(不推荐)

  • Step 1:

    1
    +
    git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git
    +
  • Step 2:

    1
    +2
    +3
    +
    // 仅克隆 esp-idf,不包含子模块
    +
    +git clone https://gitee.com/EspressifSystems/esp-idf.git
    +
  • Step 3:

可以有两种方式来更新 submodules。

  • 方式一

    进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:

    1
    +2
    +
    cd esp-gitee-tools
    +export EGT_PATH=$(pwd)
    +

    进入 esp-idf 目录执行 submodule-update.sh 脚本:

    1
    +2
    +
    cd esp-idf
    +$EGT_PATH/submodule-update.sh
    +
  • 方式二

    submodule-update.sh 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:submodule-update.sh PATH_OF_PROJ

    假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:

    1
    +2
    +
    cd esp-gitee-tools
    +./submodule-update.sh ~/git/esp32-sdk/esp-idf
    +

    如果要更新其他工程,可以同样方式。

值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!

3.Problem2 solution

下面说第二个问题:执行./install.sh速度慢的问题

在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 IDF_GITHUB_ASSETS 的环境变量来指定这个地址。在设置了 IDF_GITHUB_ASSETS 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件

1
+
export IDF_GITHUB_ASSETS="dl.espressif.com/github_assets"
+

然后再执行安装命令

1
+
./install.sh
+

在这还报了一个错误

image-20230504124717772

我们根据提示安装python3.10-venv,并再次执行安装命令:

1
+2
+3
+
apt install python3.10-venv
+
+./install.sh
+

image-20230504124913620

至此,esp-idf 的安装工具就告一段落了。

esp-matter开发环境搭建

参考:【乐鑫 Matter SDK GitHub】

**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:./jihu-mirror.sh unset取消esp镜像!! **

1
+
git clone --recursive https://github.com/espressif/esp-matter.git
+

若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。

1
+
git submodule update --init --recursive
+

执行安装命令:

1
+
./install.sh
+

本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错…

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
  Building wheel for pycryptodome (setup.py): started
+  error: subprocess-exited-with-error
+  
+  × python setup.py bdist_wheel did not run successfully.
+  │ exit code: 1
+  ╰─> See above for output.
+  
+  note: This error originates from a subprocess, and is likely not a problem with pip.
+  Building wheel for pycryptodome (setup.py): finished with status 'error'
+  ERROR: Failed building wheel for pycryptodome
+  Running setup.py clean for pycryptodome
+  Building wheel for gevent (pyproject.toml): started
+  
+  ......
+

我们查看install.sh文件

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+
#!/usr/bin/env bash
+
+set -e
+
+basedir=$(dirname "$0")
+ESP_MATTER_PATH=$(cd "${basedir}"; pwd)
+MATTER_PATH=${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip
+export ESP_MATTER_PATH
+
+echo ""
+echo "Running Matter Setup"
+echo ""
+source ${MATTER_PATH}/scripts/bootstrap.sh
+
+echo ""
+echo "Installing zap-cli"
+echo ""
+# Run the zap_download.py and extract the path of installed binary
+# eg output before cut: "export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly"
+# output after cut: zap/zap-v2023.03.06-nightly
+# TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged
+zap_path=`python3 ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py \
+    --sdk-root ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly \
+    --extract-root .zap 2>/dev/null | cut -d= -f2`
+# Check whether the download is successful.
+if [ -z $zap_path ]; then
+    echo "Failed to install zap-cli"
+    deactivate
+    exit 1
+fi
+
+# Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path
+if [ -d "${ESP_MATTER_PATH}/.zap" ]; then
+    rm -r ${ESP_MATTER_PATH}/.zap
+fi
+mkdir ${ESP_MATTER_PATH}/.zap
+mv $zap_path/* ${ESP_MATTER_PATH}/.zap/
+rm -r $zap_path
+chmod +x ${ESP_MATTER_PATH}/.zap/zap-cli
+
+echo ""
+echo "Building host tools"
+echo ""
+gn --root="${MATTER_PATH}" gen ${MATTER_PATH}/out/host
+ninja -C ${MATTER_PATH}/out/host
+echo ""
+echo "Host tools built at: ${MATTER_PATH}/out/host"
+echo ""
+
+echo ""
+echo "Exit Matter environment"
+echo ""
+deactivate
+
+echo ""
+echo "Installing python dependencies for mfg_tool"
+echo ""
+python3 -m pip install -r ${ESP_MATTER_PATH}/tools/mfg_tool/requirements.txt
+
+echo ""
+echo "Installing python dependencies for Matter"
+echo ""
+python3 -m pip install -r ${ESP_MATTER_PATH}/requirements.txt
+
+echo "All done! You can now run:"
+echo ""
+echo "  . ${basedir}/export.sh"
+echo ""
+

发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:

1
+2
+3
+4
+5
+
sudo apt install build-essential python3-dev
+
+sudo apt-get install pkg-config
+
+sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev
+

image-20230504145216015

接着在安装zap-cli的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译

1
+2
+3
+4
+5
+
sudo apt-get install libssl-dev
+
+sudo apt-get install pip
+
+./install.sh
+

image-20230504150238105

最后看到All done!即代表环境安装成功!

image-20230504153243388

至此,esp-matter开发环境搭建成功!

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 04, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634.jpg" new file mode 100644 index 000000000..49ee04344 Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634_hub61065a780e4610b8a863ce12cf0078a_240369_250x150_fill_q75_box_smart1.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634_hub61065a780e4610b8a863ce12cf0078a_240369_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..610a88c06 Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.947ed27ad15be040439a98eda2ade634_hub61065a780e4610b8a863ce12cf0078a_240369_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.jpg" new file mode 100644 index 000000000..49ee04344 Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_120x120_fill_q75_box_smart1.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c21f354de Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_1600x0_resize_q75_box.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..861ec2f84 Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_800x0_resize_q75_box.jpg" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c55e05b7e Binary files /dev/null and "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/cover_hub61065a780e4610b8a863ce12cf0078a_240369_800x0_resize_q75_box.jpg" differ diff --git "a/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/index.html" "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/index.html" new file mode 100644 index 000000000..acf837776 --- /dev/null +++ "b/p/matteresp-matter\347\216\257\345\242\203\344\270\213\347\232\204\345\272\224\347\224\250\345\256\236\350\267\265\347\250\213\345\272\217\347\203\247\345\275\225\345\217\212\344\270\262\345\217\243\347\233\221\350\247\206/index.html" @@ -0,0 +1,102 @@ +【Matter】esp-matter环境下的应用实践(程序烧录及串口监视) +
Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)

【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)

esp-matter环境下的应用实践,包括程序烧录及串口监视

+
+

esp-matter环境下的应用实践


前提准备

请确保你本地已经配置好 esp-idfesp-matter环境,可参考此博客【Matter】esp-matter开发环境搭建

设置环境变量

1.ESP-IDF

根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:

1
+
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
+

使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。

1
+2
+
cd ./esp/esp-idf
+source export.sh
+

image-20230504160909004

2.ESP-Matter

由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见此处

在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:

1
+2
+3
+
sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \
+     libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \
+     python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
+

准备编译matter所需环境。注:如切换了其他分支需要重新运行

1
+2
+
cd ./esp/esp-matter/connectedhomeip/connectedhomeip
+source scripts/bootstrap.sh
+

image-20230506013329415

激活编译matter环境

1
+2
+
cd ./esp/esp-matter/connectedhomeip/connectedhomeip
+source scripts/activate.sh
+

image-20230504161123505

Matter Example编译下载

1.激活esp-matter环境

1
+2
+
cd esp-idf
+. ./export.sh
+
1
+2
+
cd esp-matter 
+. ./export.sh
+

2.选择esp设备

1
+2
+3
+
cd esp-matter/examples/light
+
+idf.py set-target esp32c3
+

初次执行这个命令发生了如下报错:

1
+2
+3
+4
+5
+
...
+
+AttributeError: 'HTTPResponse' object has no attribute 'strict'
+
+...
+

在GitHub上参考此issue,并执行以下命令:

1
+
pip install -U "urllib3<2"
+

同时重新执行esp-matter安装脚本:

由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此issue

1
+2
+3
+4
+5
+
rm -rf esp-matter/connectedhomeip/connectedhomeip/.environment
+
+cd esp-matter
+
+./install.sh
+
1
+
pip install -U "urllib3<2"
+

然后回到示例工程下继续执行esp设备选择

1
+2
+3
+
cd esp-matter/examples/light
+
+idf.py set-target esp32c3
+

此时发生了新的错误:

image-20230506022134054

由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:

1
+2
+
sudo rm -r esp-matter/examples/light/build
+idf.py set-target esp32c3
+

最后成功解决问题:

b372338ad9384db034000d7839549b5

3.编译工程

1
+
idf.py build
+

image-20230506025001282

4.SDK烧写

第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令

1
+
idf.py erase_flash
+

image-20230506025047817

烧录程序并打开串口监视

1
+
idf.py flash monitor
+

可以看到烧录进度:

image-20230506025133178

包括串口监视器的提示信息,同时执行以下命令可退出串口监视:

1
+
CTRL + ]
+

image-20230506025401001

那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。


参考链接:

Matter Over Wifi 例程体验(CHIP Over Wifi)

ESP-Matter 环境测试

matter搭建环境

https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 06, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f.jpg" new file mode 100644 index 000000000..0220831b6 Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f_hu4db83519daded61789268b571d06530d_135204_250x150_fill_q75_box_smart1.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f_hu4db83519daded61789268b571d06530d_135204_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..91c4f0d1f Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.9ad4e2b2f78303ab8359d7113b254a1f_hu4db83519daded61789268b571d06530d_135204_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.jpg" new file mode 100644 index 000000000..0220831b6 Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_120x120_fill_q75_box_smart1.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..ac7b416f7 Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_1600x0_resize_q75_box.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..5c3dc005e Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_1600x0_resize_q75_box.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_800x0_resize_q75_box.jpg" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..8ce585119 Binary files /dev/null and "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/cover_hu4db83519daded61789268b571d06530d_135204_800x0_resize_q75_box.jpg" differ diff --git "a/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/index.html" "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/index.html" new file mode 100644 index 000000000..ab897b44b --- /dev/null +++ "b/p/mattermatter\345\255\246\344\271\240\347\254\224\350\256\2601/index.html" @@ -0,0 +1,32 @@ +【Matter】Matter学习笔记1 +
Featured image of post 【Matter】Matter学习笔记1

【Matter】Matter学习笔记1

Matter 作为一个应用级的协议,向下屏蔽了设备制造商的生态和系统,让各种智能家居设备之间能相互通信。

+
+

Matter学习笔记1


在了解Matter之前,可以选择先了解以下前提知识:

以上资料来自CSDN博主:Eagle115

前言

近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。

Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准

Matter 作为一个应用级的协议,向下屏蔽了设备制造商的生态和系统,让各种智能家居设备之间能相互通信。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。

Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:

  • 低功耗蓝牙技术:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。
  • 二维码进行配置:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。
  • Wi-Fi 技术进行高速数据传输:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。
  • Thread 协议进行低速数据传输:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。

Matter协议架构

1.Matter Over IPV6

该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。

IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。

下面是IPV4 和 IPV6 的一些区别:

区别IPV4IPV6
地址长度32 bits128 bits
地址数量4x10^93.4×10^38
地址类型公网地址和私有地址全局地址和本地地址
地址分配方式静态地址和动态地址通过 DHCPv6 动态分配
安全性IPsec(Internet协议安全标准) 为可选项IPsec 为默认选项

2.Matter协议架构

Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。

为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此天生具备IP连接能力,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;

Matter 还支持桥接等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行Bridge

由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!

3.Matter标准协议架构

Matter标准协议架构总体流程分析:

首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议Message Reliability Protocol);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。

后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!

Matter网络拓扑结构

原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。

在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。

Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层。而 6LoWPAN协议 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。

因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。

Mesh组网

在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。

目前最流行的全屋WiFi方案主要有两种:Mesh路由器组网AC+AP两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。

无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,无线Mesh网络中的AP可以采用无线连接的方式进行互连,并且AP间可以建立多跳的无线链路。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。

https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png

这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:

1.单一网络拓扑

在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是Thread/802.15.4网络Wi-Fi网络以太网网络。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,前提是所有段都在链路层桥接。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。

在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。

在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为Fabric

注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。

2.星形网络拓扑

  • AP(Access Point):WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。
  • STA(Station):STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。
  • BR(Border Router):指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。
  • ED(End device):指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。
  • R(Router):指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。
  • SED(Sleepy End Device):指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。

星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。

在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。

该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。

注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。

设备数据模型(Date Model)

在 Matter 中的设备具有明确定义的数据模型 (DM),这是对设备功能的分层建模。在此层次结构的顶层,有一个Device

1.设备和端点(Node、Endpoint)

所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。

一组节点包含了多组Endpoint(端点)而每个端点都封装了一个功能集。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。

2.节点角色(Node roles)

在Matter 中,每一个物理设备都被称之为Node,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!

Node roles是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:

  • Commissioner :执行调试的节点 。
  • 控制器:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如开/关灯开关)具有控制器角色。
  • Controlee : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如On/Off Light Switch。开/关灯开关只能控制器。它不能是受控人。
  • OTA Provider : 可以提供 OTA 软件更新的节点。
  • OTA 请求者:可以请求 OTA 软件更新的节点。

3.集群(Cluster)

在一个Endpoint中,一个 Node 有一个或多个Clusters。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的开/关集群,或可调光端点上的电平控制集群。

一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。

3.1 属性(Attributes)

在最后一层,我们会找到Attributes,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。

3.2 命令(Commands)

除了 Attributes 之外,Clusters 还有Commands,也就是触发 Cluster 进行某种行为的指令。它们等同于Matter远程过程调用的 DM。命令类似于动词,例如Door Lock集群上的 lock door。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。

3.3 事件(Events)

最后,Clusters 也可能有Events,它可以被认为是过去状态转换的记录。虽然属性代表当前状态,但事件是过去的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。

Endpoint 0作为Utility Clusters保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。

4. Cluster分类

cluster可以定义为工具(Utility) Cluster应用(Application) Cluster

4.1 工具(Utility) Cluster

工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。

作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。

4.2 应用(Application) Cluster

应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。

应用cluster示例:

  • On/Off cluster —— client向server发送命令
  • Temperature Measurement cluster —— server向client报告数据

应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。

示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。

5. Clients and Servers

Clusters 可能是Client ClusterServer Cluster。服务器是有状态的,保存属性、事件和命令;而客户端是 无状态的,其职责是启动与远程服务器集群的交互,从而执行:

  • 读取写入其远程属性。
  • 读取其远程事件。
  • 调用其远程命令。

虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有controller/peripheralleader/follower关系。相反,关系是水平的:任何 Cluster 都可以是ServerClient。因此,对于不同的集群和功能,节点可能既是服务器又是客户端。

例如,我们可能有两个台灯:节点 A节点 B。两个节点都实现了一个开/关灯设备类型。此设备类型包括控制其各自物理光输出的开/关服务器集群。

但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现开/关客户端集群,以便它可以控制服务器集群。

在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。

在下一节中,我们将详细介绍客户端和服务器集群如何交互: Interaction Model(交互模型)

交互模型

1.概念

如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。交互模型IM),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。

节点通过以下方式相互交互:

  • 读取和订阅属性和事件
  • 写入属性
  • 调用命令

每当一个节点与另一个节点建立加密通信序列时,它们就构成了交互关系。Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成,可以理解为 Node 之间的 IM 级消息。

Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。

1.1 发起者(Initiators )和目标(Targets)

在Matter中,节点的发起目标被称为发起者(Initiators ),而响应的节点则作为目标(Target)。一般来说,发起者是客户端集群,而目标是客户端集群。

1.2 组(Groups)

在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。

为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。

1.3 路径(Path)

当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。

注:Path 也可以使用Groups或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。

Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。

Matter Path 使用规范:

1
+2
+
<path> = <node> <endpoint> <cluster> <attribute | event | command>
+<path> = <group ID>        <cluster> <attribute | event | command>
+

在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。

1.4 定时和非定时(Timed & Untimed)

有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。

2. Read Transactions

与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。

2.1 读取请求操作(Read Request Action)

发起者 -> 目标

在此 Action 中,Initiator 会查询 Target 提供的以下请求:

  • 属性请求:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。
  • 事件请求:目标请求事件的零个或多个路径列表。

目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:

2.2 报告请求数据(Report Data Action)

目标 -> 发起者

在此 Action 中,Target 响应:

  • 属性报告(Attribute Reports):读取操作请求中请求的零个或多个报告属性的列表。
  • 事件报告(Event Reports):零个或多个报告事件的列表。
  • 抑制响应(Suppress Response):一个标志,用于确定是否应抑制对此操作的状态响应。
  • 订阅 ID(Subscription ID):如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。

2.3 状态响应动作(Status Response Action)

目标 -> 发起者 -> 目标

一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。

一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。

状态响应操作仅包含一个状态字段,该字段将确认操作成功或显示失败代码。

3. Subscription Transaction

3.1 订阅请求操作(Subscribe Request Action)

发起者 -> 目标

除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。

订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。

订阅请求操作包含:

  • Min Interval Floor(最小间隔层):报告之间的最小间隔。
  • Max Interval Ceiling(最大区间上限):报告之间的最大间隔。
  • Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。
  • Event Reports(事件报告):零个或多个报告事件的列表。

在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:Primed Published Data

然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。

目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。

3.2 订阅响应操作(Subscribe Response Action)

目标 -> 发起者

这是订阅交易的最后一个操作,并结束了该过程。这包括:

  • Subscription ID(订阅 ID):标识订阅的整数。
  • Min Interval(最小间隔):最终确定的报告之间的最小间隔。
  • Max Interval(最大间隔)最终确定报告之间的最大间隔。

4. Write Transactions

4.1 不定时写入事务(Untimed Write Transaction)

4.1.1 写请求操作(Write Request Action)

发起者 -> 目标

与读取请求操作类似,在此操作中,发起者为目标提供:

  • Write Requests(写入请求):包含路径和数据的一个或多个元组的列表。
  • Timed Request(定时请求):一个标志,指示此操作是否是定时写入事务的一部分。
  • Suppress Response(抑制响应):指示是否应抑制响应状态操作的标志。

4.1.2 写响应操作(Write Response Action)

目标 -> 发起者

4.1.3 不定时写入限制(Untimed Write Restrictions)

写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。

为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。

4.2 定时写入事务(Timed Write Transaction)

在定时写入事务中比非定时写入事务多了几个步骤。

4.2.1 定时请求操作(Timed request action)

发起者 -> 目标

Initiator 启动事务发送此操作,其中包含:

  • Timeout:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。

一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。

4.2.2 写请求操作(Write Request Action)

与前面描述的 4.1.1 写请求操作 相同。

4.2.3 写响应操作(Write Response Action)

与前面描述的 4.1.2 写响应操作 相同。

4.2.4 定时写入限制(Timed Write Restrictions)

定时请求动作、写请求动作和写响应动作是单播的。

5.调用事务

调用事务用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。

与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 交互模型:1.4.定时和非定时

5.1 不定时调用事务

5.1.1 调用请求操作(Invoke Request Action)

发起者 -> 目标

类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:

  • Invoke Requests(调用请求):集群命令的路径(PATH)列表 ,以及命令的可选参数,名为 Command Fields
  • Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。
  • Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。
  • Interaction ID:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。
5.1.2 调用响应操作(Invoke Response Action)

目标 -> 发起者

目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:

  • Invoke Responses(调用响应):发送的每个调用请求的命令响应或状态列表。
  • Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。
5.1.3 不定时调用限制

Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。

为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。

5.2 定时调用事务

与定时写入事务类似,定时调用事务也从定时请求操作开始。

5.2.1 定时请求操作

发起者 -> 目标

Initiator 启动事务发送此操作,其中包含:

  • Timeout:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。

一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。

5.2.2 调用请求操作(Invoke Request Action)

与前面描述的 5.1.1 调用请求操作 相同。

5.2.3 调用响应操作(Invoke Response Action)

与前面描述的 5.1.2 调用响应操作 相同。

5.2.4 定时调用限制(Timed Invoke Restrictions)

所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。

Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。


参考资料

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jun 14, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864.jpg" new file mode 100644 index 000000000..d9e87b177 Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_250x150_fill_q75_box_smart1.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c5e2633e9 Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.5ffd36259aa1f1cfcb6884e69f2af864_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.jpg" new file mode 100644 index 000000000..d9e87b177 Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_120x120_fill_q75_box_smart1.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..25036dddb Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_1600x0_resize_q75_box.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..bca4439a1 Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_1600x0_resize_q75_box.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_800x0_resize_q75_box.jpg" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9d8ffefd0 Binary files /dev/null and "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_800x0_resize_q75_box.jpg" differ diff --git "a/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/index.html" "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/index.html" new file mode 100644 index 000000000..6c881388f --- /dev/null +++ "b/p/mattermatter\347\216\257\345\242\203\346\236\204\345\273\272\345\217\202\350\200\203\346\226\207\346\241\243/index.html" @@ -0,0 +1,206 @@ +【Matter】Matter环境构建参考文档 +
Featured image of post 【Matter】Matter环境构建参考文档

【Matter】Matter环境构建参考文档

Matter支持用 GN 配置构建,一个快速且可扩展的元构建系统,生成输入到 ninja 。

+
+

Matter 环境构建参考文档


Matter支持用GN配置构建,一个快速且可扩展的元构建系统,生成输入到ninja

经过测试的操作系统

该构建系统已经在以下操作系统上进行了测试:

  • macOS 10.15
  • Debian 11 (64 bit required)
  • Ubuntu 22.04 LTS

构建系统的特点

Matter构建系统有以下特点:

  • 速度非常快,占用空间小
  • 跨平台处理: Linux, Darwin, Embedded Arm, 等等
  • 多种工具链和跨工具链的依赖性
  • 集成了自动测试框架: ninja check
  • 自省:“gn desc”。
  • 自动格式化: gn格式

检查Matter的代码

要检查Matter资源库,请运行以下命令:

1
+
git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git
+

同步子模块

如果你已经签出了Matter的代码,运行下面的命令来同步子模块:

1
+
git submodule update --init
+

先决条件

在构建之前,你必须安装一些操作系统的特定依赖。

1.在Linux上安装先决条件

在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:

1
+2
+3
+
sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\
+     libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev
+     python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
+

用户界面的构建

如果通过build_examples.pywith-ui变体构建,也要安装SDL2:

1
+
sudo apt-get install libsdl2-dev
+

2.在macOS上安装先决条件

在macOS上,从 Mac App Store上安装 Xcode 。

用户界面的构建

如果构建-with-ui变体,也要安装 SDL2 :

1
+
brew install sdl2
+

3.在Raspberry Pi 4上安装先决条件

完成以下步骤:

  1. 使用:在 micro SD 卡上rpi-imager安装适用于 arm64 架构的 Ubuntu 22.04 64 位服务器操作系统。
  2. 启动SD卡。
  3. 用默认的用户账户 “ubuntu “和密码 “ubuntu “登录。
  4. 继续执行 在 Linux 上安装先决条件
  5. 安装一些Raspberry Pi的特定依赖项:
1
+
sudo apt-get install pi-Bluetooth avahi-utils
+
  1. 安装完 “pi-bluetooth “后,重新启动你的Raspberry Pi。

配置wpa_supplicant以存储永久变化

默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:

  1. 编辑 dbus-fi.w1.wpa_supplicant1.service 文件以使用配置文件来代替,运行以下命令:
1
+
sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service
+
  1. 运行以下命令,将wpa_supplicant的启动参数改为提供的值:
1
+
ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
+
  1. 通过运行以下命令添加wpa-supplicant配置文件:
1
+
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
+
  1. wpa-supplicant文件中添加以下内容:
1
+2
+
ctrl_interface=DIR=/run/wpa_supplicant
+update_config=1
+
  1. 重新启动你的Raspberry Pi。

安装ZAP工具

bootstrap.sh将下载一个兼容的ZAP工具版本并将其设置在$PATH。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的Release 页面下载。

1.Linux ARM

Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置$ZAP_DEVELOPMENT_PATH(见下面 使用哪种ZAP一节)。

文件scripts/setup/zap.json包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本Release。要作为源代码签出代码,相应的标签应该存在于zap中repository tags 列表中。

命令示例:

1
+2
+3
+4
+5
+6
+7
+8
+
RUN set -x \
+    && mkdir -p /opt/zap-${ZAP_VERSION} \
+    && git clone https://github.com/project-chip/zap.git /opt/zap-${ZAP_VERSION} \
+    && cd /opt/zap-${ZAP_VERSION} \
+    && git checkout ${ZAP_VERSION} \
+    && npm config set user 0 \
+    && npm ci
+ENV ZAP_DEVELOPMENT_PATH=/opt/zap-${ZAP_VERSION}
+

2.使用哪种ZAP

ZAP工具脚本使用以下检测,按重要性排序:

  • $ZAP_DEVELOPMENT_PATH指向一个ZAP检出。

  • 如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。

  • $ZAP_INSTALL_PATH指向zap-linux.zip或`zap-m

为构建做准备

在运行任何其他构建命令之前,scripts/activate.sh的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。

运行以下命令:

1
+
source scripts/activate.sh
+

1.更新环境

如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:

1
+
source scripts/bootstrap.sh
+

脚本 scripts/bootstrap.sh从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。

为主机操作系统(Linux或macOS)进行构建

运行以下命令,为主机平台构建所有的源代码、库和测试:

1
+2
+3
+4
+5
+
source scripts/activate.sh
+
+gn gen out/host
+
+ninja -C out/host
+

这些命令生成了一个适合调试的配置。要配置一个构建,请指定is_debug=false

1
+2
+3
+
gn gen out/host --args='is_debug=false' 。
+
+ninja -C out/host
+

**注意:**目录名称 “out/host “可以是任何目录,通常是在out目录下构建。这个例子使用 host 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过gn args重新配置。

要运行所有测试,请运行以下命令:

1
+
ninja -C out/host check
+

要想只运行src/inet/tests中的测试,可以运行以下命令:

1
+
ninja -C out/host src/inet/tests:test_run
+

**注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:

1
+
ninja: no work to do
+

这意味着测试在之前的构建中通过了。

使用build_examples.py

该脚本./scripts/build/build_examples.py提供了一个统一的编译构建接口,可以使用gncmakeninja和其他必要的工具来编译各种平台。

使用 ./scripts/build/build_examples.py targets 来查看支持的目标。

构建命令的例子:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
# 编译并在主机上运行所有测试:
+./scripts/build/build_examples.py --target linux-x64-test build
+
+# 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang)
+./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build
+
+# 编译一个esp32的例子
+./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build
+
+# 编译一个 nrf 示例
+./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build
+

1.libfuzzer单元测试

libfuzzer单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如asan应该被使用。

可执行以下命令:

1
+
./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build
+

之后,测试应该被定位在out/linux-x64-tests-lang-asan-libfuzzer/tests/

ossfuzz的配置

ossfuzz配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如$CFLAGS$CXXFLAGS$lib_fuzzing_engine

你可能需要libfuzzer+asan的构建来代替本地测试。

构建自定义配置

构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:

  • --args选项传递给gn gen
  • 在输出目录上运行gn args
  • 编辑输出目录下的args.gn

要配置一个新的构建或编辑现有构建的参数,请运行以下命令:

1
+2
+3
+4
+5
+
source scripts/activate.sh
+
+gn args out/custom
+
+ninja -C out/custom
+

两个关键的内置构建参数是 target_ostarget_cpu,它们分别控制构建的操作系统和CPU。

要查看所有可用的构建参数的帮助,请运行以下命令:

1
+2
+
gn gen out/custom
+gn args --list out/custom
+

构建实例

你可以通过两种方式构建例子。

1.将例子作为独立的项目来构建

要把例子作为单独的项目来构建,在Matter的third_party directory,运行下面的命令,输入正确的路径到例子的正确路径(这里是 “chip-shell”):

1
+2
+3
+
cd examples/shell
+gn gen out/debug
+ninja -C out/debug
+

2.在顶层建立实例

你可以在Matter项目的顶层构建例子。请看下面的统一构建一节了解详情。

统一构建

要构建一个近似于连续构建集的统一配置,请运行以下命令:

1
+2
+3
+4
+5
+
source scripts/activate.sh
+
+gn gen out/unified --args='is_debug=true target_os="all"'
+
+ninja -C out/unified all
+

你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。

这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:

1
+2
+
ninja -C out/unified host_gcc
+ninja -C out/unified check_host_gcc
+

用配置的名称替换host_gcc,它可以在根目录下的 “BUILD.gn “中找到。

你也可以用参数对生成的配置进行微调。比如说

1
+
gn gen out/unified --args='is_debug=true target_os="all" enable_host_clang_build=false'
+

完整的列表请参见根目录BUILD.gn

在统一的构建中,目标有多个实例,需要通过添加通过添加(toolchain)后缀来区分。使用gn ls out/debug来列出所有的目标实例。例如:

1
+
gn desc out/unified '//src/controller(//build/toolchain/host:linux_x64_clang)'
+

**注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 +必须作为构建参数提供。例如,要添加 Simplelink cc13x2_26x2 例子到统一构建中,安装SysConfig 并添加以下构建:

1
+
gn gen out/unified --args="target_os=\"all\" enable_ti_simplelink_builds=true > ti_sysconfig_root=\"/path/to/sysconfig\""
+

获得帮助

GN集成了帮助,你可以通过gn help命令访问。

请确保查看以下推荐的主题:

1
+2
+3
+
gn帮助执行
+gn help 语法
+gn help toolchain
+

也可参见 快速入门指南

自省

GN有各种自省工具来帮助你检查构建配置。下面的例子以out/host输出目录为例:

  • 显示一个输出目录中的所有目标:

    1
    +
    gn ls out/host
    +
  • 显示所有将被构建的文件:

    1
    +
    gn output out/host '*'
    +
  • 显示配置的目标的GN表示:

    1
    +
    gn desc out/host //src/inet --all
    +
  • 将整个构建的GN表示转为JSON格式:

    1
    +
    gn desc out/host/ '*' --all --format=json
    +
  • 显示依赖关系树:

    1
    +
    gn desc out/host //:all deps --tree --all
    +
  • 查找依赖性路径:

    1
    +
    gn path out/host //src/transport/tests:test //src/system
    +
  • 列出与`libCHIP’连接的有用信息:

    1
    +2
    +3
    +4
    +5
    +6
    +
    gn desc out/host //src/lib include_dirs
    +gn desc out/host //src/lib defines
    +gn desc out/host //src/lib outputs
    +
    +# 一切都是JSON格式
    +gn desc out/host //src/lib --format=json
    +

覆盖范围

代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。

运行以下命令来启动该脚本:

1
+
./scripts/build_coverage.sh
+

默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:

1
+2
+3
+4
+5
+6
+7
+8
+
  -c, --code 指定收集覆盖数据的范围。
+                            core":从Matter SDK的核心堆栈中收集覆盖数据。--default
+                            clusters":从Matter SDK中的cluster实现中收集覆盖数据。
+                            'all':收集Matter SDK的覆盖数据。
+  -t, --tests 指定哪些工具来运行覆盖率检查。
+                            'unit': 运行单元测试来驱动覆盖率检查。--default
+                            'yaml': 运行yaml测试来驱动覆盖率检查。
+                            'all': 运行单元和yaml测试来驱动覆盖率检查。
+

此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): matter coverage

维护事项

如果你对GN构建系统做了任何改变,下一次构建会自动重新生成ninja文件。不需要做任何事情。

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 24, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4.jpg" new file mode 100644 index 000000000..3c02efa20 Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4_huc64212d66a303c0299db7891fa23c614_59145_250x150_fill_q75_box_smart1.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4_huc64212d66a303c0299db7891fa23c614_59145_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..0a9f1bf72 Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.23bae6bbeff4cfbcb00de49b11bb41a4_huc64212d66a303c0299db7891fa23c614_59145_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.jpg" new file mode 100644 index 000000000..3c02efa20 Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_120x120_fill_q75_box_smart1.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..cd2abc220 Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_1600x0_resize_q75_box.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..62e49679c Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_800x0_resize_q75_box.jpg" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..80aee522b Binary files /dev/null and "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/cover_huc64212d66a303c0299db7891fa23c614_59145_800x0_resize_q75_box.jpg" differ diff --git "a/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/index.html" "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/index.html" new file mode 100644 index 000000000..73a1fe02b --- /dev/null +++ "b/p/matternordic-mattter\345\274\200\345\217\221\345\244\247\347\272\262/index.html" @@ -0,0 +1,27 @@ +【Matter】Nordic-Mattter开发大纲 +
Featured image of post 【Matter】Nordic-Mattter开发大纲

【Matter】Nordic-Mattter开发大纲

这部分仅作为开发大纲,后面会出一系列系统教程,以 Matter over Thread:在一台设备上配置边界路由器和控制器 为例。

+
+

nRF Connect SDK 支持Mattter

子页面:

Matter网络拓扑结构

image-20230601200431602

  • Thread:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。
  • WI-FI:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。
  • Ethernet(以太网):Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。
  • Matter binding(Matter协议):Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。

硬件平台

运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。

硬件参考

  • Nodic nRF52840
  • PC: Ubuntu(20.04 或更新版本)
  • Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)
  • 支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)
  • RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备
  • 兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个Matter 样本兼容并编程)

软件平台

Linux PC withsoftware installed:

商业Matter生态系统测试方式

对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:

注意:这里我们基于Matter over Thread:在一台设备上配置边界路由器和控制器进行过程演示。


Matter over Thread::在一台设备上配置边界路由器和控制器

如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。

在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。

下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发

image-20230605205336833

1.要求

若要使用此设置,需要以下硬件:

  • 以下任意之一:
    • 1 台装有 Ubuntu 的电脑(20.04 或更高版本)
    • 1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS
  • 1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)
  • 1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备
  • 1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用物质样品之一进行编程))

2.配置环境

要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。

Step1.对样品编程

使用可用的 Matter 样本之一对 Matter 附件设备的开发套件进行编程。 我们建议使用Matter light bulb

Step2.Thread Border Router配置

在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 Thread Border Router页面上的使用 Docker 运行 OTBR 部分。

Step3.Chip Tool配置

适用于 Linux 或 macOS 的 CHIP Tool 是 Matter controller 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。

完成以下步骤:

a. 选择以下选项之一:

  • 仅适用于 Linux - 使用 Matter nRF Connect 发布 GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。
  • 对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 CHIP TOOL页面中的构建说明。modules/lib/matter/examples/chip-tool

b. 配置芯片工具控制器。 按照 Matter 文档中的使用 CHIP TOOL用户指南中的步骤完成以下操作:

  • 通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。
  • 通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。

Step4.例程测试

根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。

结语

这部分仅作为开发大纲,后面会出一系列系统教程,以Matter over Thread::在一台设备上配置边界路由器和控制器为例。


+Licensed under CC BY-NC-SA 4.0
+Last updated on Jun 07, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949.jpg" new file mode 100644 index 000000000..14b1b4ea5 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949_hu0ba98275d6445c79f820f07c37ff307c_166978_250x150_fill_q75_box_smart1.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949_hu0ba98275d6445c79f820f07c37ff307c_166978_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..e0bd3ca72 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.b05a89bff572086ca06cc577a29f3949_hu0ba98275d6445c79f820f07c37ff307c_166978_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.jpg" new file mode 100644 index 000000000..14b1b4ea5 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_120x120_fill_q75_box_smart1.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..dc75a1493 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_1600x0_resize_q75_box.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ac1660ee2 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_800x0_resize_q75_box.jpg" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..77d5ef319 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_800x0_resize_q75_box.jpg" differ diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/index.html" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/index.html" new file mode 100644 index 000000000..d82635a8d --- /dev/null +++ "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/index.html" @@ -0,0 +1,218 @@ +【Matter】使用chip-tool在ESP32-C3上进行matter开发 +
Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发

【Matter】使用chip-tool在ESP32-C3上进行matter开发

使用chip tool在ESP32-C3上进行matter开发

+
+

使用chip tool在ESP32-C3上进行matter开发


前提准备

编译 chip-tool

1.激活esp-matter环境

1
+2
+
cd esp-idf
+. ./export.sh
+
1
+2
+
cd esp-matter 
+. ./export.sh
+

2.编译matter所需环境

  • step1:首先安装编译所需的依赖包:
1
+
sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
+
  • step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)
1
+2
+3
+
# 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新
+
+source scripts/bootstrap.sh
+

对于 MacOS,gdbguipython 包不会使用bootstrap.sh 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为gevent(依赖于gdbgui)构建轮子失败。

对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。

如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件

1
+2
+
python3 -m pip install -c scripts/setup/constraints.txt --no-cache --prefer-binary gdbgui==0.13.2.0
+deactivate
+
  • step3:激活编译matter环境
1
+
source scripts/activate.sh
+
  • step4:启用 Ccache 以加快 IDF 构建速度
1
+
$ export IDF_CCACHE_ENABLE=1
+

3.构建CHIP TOOL

~/esp/esp-matter/connectedhomeip/connectedhomeip目录下,执行命令

1
+
./gn_build.sh
+

image-20230504173815084

执行完之后,会在根目录下生成 out/debug/standalone/chip-tool一个二进制文件。

image-20230504174038993

如果上述命令:./gn_build.sh执行失败,也可以执行如下命令:

1
+
scripts/examples/gn_build_example.sh examples/chip-tool SOME-PATH/
+

image-20230504175634584

执行完毕后,在以下路径 connetedhomeip/connectedhomeip/SOME-PATH也可以发现生成了 chip-tool 工具

image-20230504175700807

chip-tool client 调试设备说明

为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前一次只支持调试和记忆一个设备。配置状态存储在/tmp/chip_tool_config.ini中;

另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
# 获取受支持集群的列表
+
+Usage:
+  ./chip-tool cluster_name command_name [param1 param2 ...]
+
+  +-------------------------------------------------------------------------------------+
+  | Clusters:                                                                           |
+  +-------------------------------------------------------------------------------------+
+  | * barriercontrol                                                                    |
+  | * basic                                                                             |
+  | * colorcontrol                                                                      |
+  | * doorlock                                                                          |
+  | * groups                                                                            |
+  | * iaszone                                                                           |
+  | * identify                                                                          |
+  | * levelcontrol                                                                      |
+  | * onoff                                                                             |
+  | * pairing                                                                           |
+  | * payload                                                                           |
+  | * scenes                                                                            |
+  | * temperaturemeasurement                                                            |
+  +-------------------------------------------------------------------------------------+
+

image-20230504180042312

要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:

1.基于 BLE 调试

运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:

1
+
chip-tool pairing ble-wifi ${NODE_ID_TO_ASSIGN} ${SSID} ${PASSWORD} 20202021 3840
+
  • ${NODE_ID_TO_ASSIGN}(必须是十进制数或0x- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。
  • ${SSID} 是 Wi-Fi SSID 可以是字符串,也可以是hex:XXXXXXXX SSID 的字节被编码为两位十六进制数字的形式。
  • ${PASSWORD} 是 Wi-Fi 密码,同样是字符串或十六进制数据
1
+2
+
# 例如
+chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq 202021 3840
+

2.通过IP与设备配对

下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。

1
+
chip-tool pairing onnetwork ${NODE_ID_TO_ASSIGN} 20202021
+

下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。

1
+
chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840
+

下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。

1
+
chip-tool pairing code ${NODE_ID_TO_ASSIGN} MT:#######
+

在所有这些情况下,将为设备分配节点 ID ${NODE_ID_TO_ASSIGN} (必须是十进制数或以 0x 为前缀的十六进制数)。

3.Trust store

Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 –paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。

下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。

1
+
chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 --paa-trust-store-path path/to/PAAs
+

4.忘记当前委托的设备

1
+
chip-tool pairing unpair
+

使用chip-tool点灯

1.matter环境激活

由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:

  • step1:新建一个名为 matter.sh 的脚本文件
1
+
vi matter.sh
+
  • step2:复制以下内容到 matter.sh
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
#/bin/bash
+# matter.sh
+
+EPS_MATTER_PATH="/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter"
+
+if [ $1 -eq 1 ]; then
+    export IDF_PATH="/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf" 
+    source /home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf/export.sh
+    source $EPS_MATTER_PATH/export.sh
+    export IDF_CCACHE_ENABLE=1
+    
+    echo "enter matter dir"
+    cd $EPS_MATTER_PATH
+fi
+
  • step3:执行脚本以激活 matter 环境
1
+
source matter.sh 1
+

2.固件烧录

  • 打开一个新的终端1,进入示例目录设置并编译烧写到评估板运行
1
+
cd ./esp/esp-matter/examples/light
+
  • 设置要构建的 Matter 目标
  • 目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标
1
+2
+3
+4
+5
+
# 命令1,通用命令,ESP32H2请执行命令2
+idf.py set-target (target chip)
+
+# 命令2,ESP32H2专用命令
+idf.py --preview set-target esp32h2
+

这里我使用的是 ESP32C3,所以执行以下命令即可

1
+
idf.py set-target esp32c3
+
  • 配置选项(可遵循默认配置即可,非特定配置可跳过这一步)

构建特定配置(示例m5stack):

1
+2
+
rm sdkconfig
+idf.py -D 'SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults' build
+

注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。

要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:

1
+
idf.py menuconfig
+
  • 构建应用程序
1
+
idf.py build
+
  • 擦除Flash

构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。

请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在functional description diagram中有所提及。

1
+2
+
idf.py -p (PORT) erase_flash
+idf.py -p (PORT) flash monitor
+

请替换(PORT)为您系统的正确 USB 设备名称(如/dev/ttyUSB0在 Linux 或/dev/tty.usbserial-101Mac 上)。

查看USB设备,esp32c3设备名为 ttyUSB0,因此执行以下命令 :

1
+2
+
idf.py -p /dev/ttyUSB0 erase_flash
+idf.py -p /dev/ttyUSB0 flash monitor
+
  • 注意此时的设备串口终端1暂时先不关闭,后面可使用CTRL+]关闭设备串口调试

image-20230530173001926

注意:某些用户可能必须在设备出现在 /dev/tty 之前安装VCP 驱动程序。

提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。

3.项目调试

以下四种方式可以用于调试在ESP32上运行应用程序:

注:这里使用 Standalone chip-tool进行项目调试

打开一个新的终端2,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:

1
+2
+3
+4
+
cd esp-matter/connectedhomeip/connectedhomeip
+
+# 激活matter环境
+source scripts/activate.sh
+

image-20230530172301207

  • 调试WIFI设备(ESP32、ESP32C3、ESP32S3)

如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看此链接

执行下面命令将 matter 设备接入现有现有IP网络,这里我们基于BLE调试

需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个购买链接

接下来请按照我的步骤一步步执行:

  • step1:安装 blueman 软件
1
+2
+
sudo apt install blueman #安装blueman软件
+sudo /etc/init.d/bluetooth restart  # 重启blueman服务
+
  • step2:确保你的蓝牙状态处于激活状态
1
+2
+3
+
# 查看蓝牙状态
+
+sudo systemctl status bluetooth
+

7e8b531f8b4be994ed272cf2e69703c

如果未运行,请执行:

1
+2
+
sudo systemctl enable bluetooth
+sudo systemctl start bluetooth
+
  • step3:确认蓝牙适配器已经被识别并启用
1
+
hciconfig -a
+

LRHC%H77T8AU FZ_V$F@(Q6

根据提示信息我们可以得知我的蓝牙适配器名为"hci0",并且状态为 “DOWN”,因此我们需要启用该蓝牙适配器。

  • step4:启用蓝牙适配器
1
+
sudo hciconfig hci0 up
+
  • step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击Adapters...--->Visibility Setting--->Always visible,这一步很关键,每次基于 BLE 调试都需要检查这一步!!

image-20230530174457873

  • step6:BLE调试,回到终端2,执行如下命令
1
+2
+3
+
cd esp-matter/connectedhomeip/connectedhomeip
+    
+out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq 20202021 3840
+

注意:本机ip和matter设备ip必须在同一局域网下

  • 0x7283(必须是十进制数或0x- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。
  • jetbot 是 Wi-Fi SSID 可以是字符串,也可以是hex:XXXXXXXX SSID 的字节被编码为两位十六进制数字的形式。
  • jetbotwyq 是 Wi-Fi 密码,同样是字符串或十六进制数据

image-20230530175437844

终端1我们可以看到相关的ip信息:

image-20230530175633102

  • step7:利用 chip tool 控制LED开关
1
+2
+3
+4
+
# open led
+out/debug/chip-tool onoff on 0x7896 0x1
+# close led
+out/debug/chip-tool onoff off 0x7896 0x1
+

这里的节点ID:0x7896需要和前面保持一致

cd20c5fede056bf65b089da69ab9f3a

f40b925710de89f66bf9ecf7ef27d7e

CHIP TOOL基于BLE调试完整过程


参考

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 30, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/video.mp4" "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/video.mp4" new file mode 100644 index 000000000..1a32d7887 Binary files /dev/null and "b/p/matter\344\275\277\347\224\250chip-tool\345\234\250esp32-c3\344\270\212\350\277\233\350\241\214matter\345\274\200\345\217\221/video.mp4" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422.jpg" new file mode 100644 index 000000000..51b650520 Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422_hu65dff124932dfb42ad926fa313c00f10_270892_250x150_fill_q75_box_smart1.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422_hu65dff124932dfb42ad926fa313c00f10_270892_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..38a09b559 Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.af97cf817061709b1b85fd365035b422_hu65dff124932dfb42ad926fa313c00f10_270892_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.jpg" new file mode 100644 index 000000000..51b650520 Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_120x120_fill_q75_box_smart1.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..ead1adf71 Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_1600x0_resize_q75_box.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c9746d83b Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_1600x0_resize_q75_box.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_800x0_resize_q75_box.jpg" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f84760129 Binary files /dev/null and "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/cover_hu65dff124932dfb42ad926fa313c00f10_270892_800x0_resize_q75_box.jpg" differ diff --git "a/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/index.html" "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/index.html" new file mode 100644 index 000000000..3fab5013b --- /dev/null +++ "b/p/matter\345\246\202\344\275\225\345\234\250linux\345\271\263\345\217\260\344\270\213\346\265\213\350\257\225matter\345\272\224\347\224\250\347\272\247\351\200\232\344\277\241\350\231\232\346\213\237\350\256\276\345\244\207/index.html" @@ -0,0 +1,106 @@ +【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备) +
Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)

【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)

如何在Linux平台下测试Matter应用级通信(虚拟设备)

+
+

如何在Linux平台下测试Matter应用级通信(虚拟设备)


准备工作

1. 递归克隆Matter仓库

执行如下命令:

1
+
git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git
+

如果克隆过程中发生报错,请执行如下命令来同步子模块:

1
+
git submodule update --init
+

由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下

1
+
git checkout v1.0
+

2. Matter依赖项安装

Matter 构建依赖于以下软件包及环境库:

1
+2
+3
+
sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \
+     libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \
+     python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
+

如果通过 build_examples.py-with-ui 变体进行构建,也要安装 SDL2:

1
+
sudo apt-get install libsdl2-dev
+

3. Matter环境构建

执行scripts/activate.sh脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。

1
+
source scripts/activate.sh
+

image-20230619083303148

如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):

1
+
source scripts/bootstrap.sh
+

4. 安装zap

注意:zap 包目前不可用arm64(比如在 Raspberry PI 上编译时)。

  • **Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:
1
+
node -v
+

如果安装的话不出意外会出现版本号。

  • Step2:zap安装
1
+2
+3
+
cd connectedhomeip/scripts/tools/zap
+
+python3 zap_download.py
+

下面是安装日志:

1
+2
+3
+4
+5
+6
+
root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py 
+2023-06-19 13:28:22 root INFO    Found required zap version to be: v2023.04.27-nightly
+2023-06-19 13:28:22 root INFO    Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip
+2023-06-19 13:29:20 root INFO    Data downloaded, extracting ...
+2023-06-19 13:29:25 root INFO    Done extracting.
+export ZAP_INSTALL_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly
+
  • Step3:配置zap环境变量

我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly,在此目录下有个 zap 脚本,我们这个位置一定要记住!!

设置ZAP_DEVELOPMENT_PATH环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)

1
+
export ZAP_DEVELOPMENT_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly
+
  • Step4:运行zap引导程序

执行如下代码:

1
+
./run_zaptool.sh
+

效果如下:

image-20230619134658521

  • Step4:为了方便我们后续使用zap,我们设置root终端下自启动:
1
+2
+3
+
sudo su
+
+vi ~/.bashrc
+

.bashrc文件最末添加如下代码,也就是配置zap环境变量

1
+
export ZAP_DEVELOPMENT_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly
+

保存退出!

应用程序构建

在官方文档中提供有两种构建方式:

  • 通过脚本构建
  • 使用 Gn 和 Ninja 命令构建

1. 通过脚本构建

1
+
./build_script.sh EXAMPLE_DIR OUTPUT_DIR [ARGUMENTS]
+
  • build_script.sh 是脚本的文件名;
  • EXAMPLE_DIR 是示例项目的目录路径;
  • OUTPUT_DIR 是构建输出的目录路径;
  • [ARGUMENTS] 是可选的其他参数,用于设置gn和ninja命令的选项。

1.1 构建示例

1
+
./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ chip_tests_zap_config=\"app1\"
+

image-20230619083551820

1.2 运行构建

1
+
./out/simulated/chip-app1
+

image-20230619084309631

2. 通过 gn 和 ninja 构建应用程序

2.1 构建示例

1
+2
+3
+
source scripts/activate.sh
+gn gen --check --root=examples/placeholder/linux out/simulated --args="chip_tests_zap_config=\"app1\""
+ninja -C out/simulated
+

2.2 运行构建

1
+2
+3
+
cd 
+
+./out/app1/chip-app1
+

image-20230619151054483

测试应用程序

在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码

image-20230619151353417

我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:

1
+2
+3
+4
+5
+6
+
cd out/debug
+
+./chip-tool onoff on 0x654321 1
+./chip-tool onoff off 0x654321 1
+./chip-tool onoff read accepted-command-list 0x654321 1
+./chip-tool onoff read on-time 0x654321 1
+

image-20230619153015727

具体更多的使用命令可参考:Chip tool


参考

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jun 19, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover.jpg" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover.jpg" new file mode 100644 index 000000000..c74a68361 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover.jpg" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_120x120_fill_q75_box_smart1.jpg" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..1f192b9c4 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1600x0_resize_q75_box.jpg" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f2ac62ae8 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1600x0_resize_q75_box.jpg" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_800x0_resize_q75_box.jpg" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..cbcacf0ae Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_800x0_resize_q75_box.jpg" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" new file mode 100644 index 000000000..0ec4ba40c Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..d20986764 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..e30f0ee30 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" new file mode 100644 index 000000000..e2cee129f Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..0f580386b Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..454755ce9 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" new file mode 100644 index 000000000..469cea159 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..a6a5e4521 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..bf00d3352 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" new file mode 100644 index 000000000..46b779103 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..a1f4cb3dc Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..f62cf521f Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" new file mode 100644 index 000000000..665de3be2 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..8266efc56 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..207f0e1d1 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" new file mode 100644 index 000000000..c74a68361 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..e61446372 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..3cacd7ba9 Binary files /dev/null and "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/index.html" "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/index.html" new file mode 100644 index 000000000..130d07eef --- /dev/null +++ "b/p/micro_ros\345\234\250rt-thread\344\270\212\350\277\220\350\241\214micro_ros/index.html" @@ -0,0 +1,203 @@ +【Micro_ROS】在RT-Thread上运行micro_ros +
Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros

【Micro_ROS】在RT-Thread上运行micro_ros

Micro-ROS的目标是将ROS2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统

+
+

快速上手micro ros && RT-Thread(serial和udp方式)

1.背景介绍

Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。

Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。

  • micro ros分层模块架构

以下是Micro-ROS的一些关键特点和概念:

  1. 嵌入式系统支持: Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。

  2. 实时性和硬件抽象: Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。

  3. 通信和中间件: Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。

  4. 适用于机器人和自动化: Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。

  5. 可扩展性: Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。

  6. 开源: Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。

本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。

2.工程准备工作

2.1 克隆 RT-Thread主仓

1
+
$ git clone https://github.com/RT-Thread/rt-thread.git
+

2.2 克隆 env-windows

1
+
$ git clone --recursive --depth 1 https://github.com/RT-Thread/env-windows.git
+

克隆下来的 env-windows 可以放在D盘,同时双击打开 env.exe,待启动ConEmu终端后将其注册到鼠标右键快捷方式

screenshot_image.png

3.编译准备工作

3.1 python & cmake安装

首先去官网安装如下工具:

  • python(大于python36):https://www.python.org/downloads/windows/
  • cmake(大于v3.22):https://cmake.org/files/

3.2 scons工具安装

打开 windows powershell ,使用 python 安装 scons

1
+
$ pip3 install scons
+

3.3 GNU make安装

GNU make 的安装可以参考该 issue 的三种方式

这里我选择的是使用choco安装make,打开windows powershell(管理员):

1
+2
+
$ Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+$ choco install make
+

3.4 Fastgithub安装

为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub

4.工程配置

选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark

1
+
$ cd .\rt-thread\bsp\stm32\stm32f407-rt-spark
+

4.1 指定工具链

去官网下载 gcc-arm-none-eabi-10-2020-q4-major-win32工具链,注意不用配置到环境变量中,以免发生冲突

修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链

screenshot_image.png

4.2 micro_ros 软件包配置

回到.\rt-thread\bsp\stm32\stm32f407-rt-spark目录下,打开 ConEmu 执行如下命令生成 packages 目录

1
+2
+
$ pkgs --update
+$ cd packages
+

克隆 micro_ros 配置仓库

1
+
$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git
+

我们来看下目录层次:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+
├─micro_ros_rtthread_component
+│  ├─.images
+│  ├─builder
+│  │  ├─extra_packages
+│  │  ├─metas
+│  │  ├─microros_utils
+│  │  └─patchs
+│  │      ├─foxy
+│  │      └─humble
+│  ├─docs
+│  ├─examples
+│  ├─include
+│  ├─package
+│  │  └─micro_ros_rtthread_package
+│  └─src
+

这里我们需要将micro_ros_rtthread_package目录复制一份到..\env-windows\packages目录下,同时修改..\env-windows\packages\Kconfig内容如下:

1
+2
+
source "$PKGS_DIR/packages/Kconfig"
+source "$PKGS_DIR/micro_ros_rtthread_package/Kconfig"
+

4.3 指定Cmake编译工具链

想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 libmicroros.a静态链接库文件,下面是 micro_ros Cmake 的相关配置:

回到目录:..\rt-thread\bsp\stm32\stm32f407-rt-spark

使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:

1
+
$ scons --target=cmake
+

此时我们在当前目录下就可以看见一个 CMakeLists.txt文件了,同时我们进入目录.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder,找到toolchain.cmake文件,参考前面生成的CMakeLists.txt文件修改toolchain.cmake

screenshot_image.png

4.4 micro ros 在 ENV 中的配置

再次回到..\rt-thread\bsp\stm32\stm32f407-rt-spark目录下,打开 ENV 勾选配置:

1
+2
+3
+4
+5
+
[*] micro-ROS package for RTThread                                    
+                [*]   Include examples                                                       
+                      Distribution (Foxy)  --->                                                   
+                      Memory configuration  --->                                                     
+                      ROS node communication mode (serial)  --->
+

其中在Memory configuration中的PublishersSubscribers这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 serial

此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!

同时我们使用 vscode 打开文件packages\micro_ros_rtthread_component\src\rtt_serial_transport.c,搜索宏MICRO_ROS_SERIAL_NAME并修改为你新创建的串口设备名。

5.开始编译

回到.\rt-thread\bsp\stm32\stm32f407-rt-spark目录下,鼠标右键打开 windows powershell ,输入如下命令:

1
+
scons --build_microros
+

此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 C:\Users\$user\AppData\Local\Temp\micro

这里的配置项主要位于packages\micro_ros_rtthread_component\builder\SConscript文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布

screenshot_image.png

编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a文件,同时将C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include目录复制到packages\micro_ros_rtthread_component\builder\libmicroros\include目录下

编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上

附:这里说下 GCC-AR 是什么:GCC-AR 是 gcc配套的库管理工具,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。

screenshot_image.png

6.WSL安装及 usbipd 支持

  • WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述

  • Docker安装:打开 wsl 终端,使用官网脚本一键安装即可

1
+2
+
$ curl -fsSL https://test.docker.com -o test-docker.sh
+$ sudo sh test-docker.sh
+
  • usbipd支持

请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html

7.serial测试

此处仅给出相关命令,具体流程请参考演示视频:

1
+2
+3
+4
+5
+6
+7
+8
+9
+
# windows powershell端
+$ usbipd wsl list	// 查看系统USB设备列表
+$ usbipd wsl attach --hardware-id "usb-id"		// 连接usb至wsl
+
+# wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)
+$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0		// 运行docker microros:foxy代理
+$ ros2 topic list	// 查看ros topic列表
+$ ros2 topic echo /micro_ros_rtt_subscriber		// 打印话题详情
+$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32  data:\ 10	// 发布topic data值为10
+

演示视频:[点击此处精准空降: microros_rtt_serial]

8.udp4测试

8.1 准备工作

首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**鱼香大佬的网站**

注意:我们安装的ros版本为 ros:foxy

继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
# 激活ros:foxy环境
+$ source /opt/ros/foxy/setup.bash
+
+# 创建工作区并拉取micro_ros_setup仓库
+$ mkdir /home/$user/microros_ws && cd /home/$user/microros_ws
+$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup
+
+# 更新rosdep
+$ sudo apt update
+$ export ROSDISTRO_INDEX_URL=https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml
+$ rosdep update --include-eol-distros
+$ rosdep install --from-paths src --ignore-src -y
+
+$ sudo apt-get install python3-pip
+
+# colcon编译
+$ colcon build
+$ source install/local_setup.bash
+
+ps:如果提示找不到colcon命令,使用如下方式安装colcon
+
+sudo apt install python3-colcon-common-externsions    # linux
+python3 -m pip install colcon-common-externsions      # macos
+pip install -U colcon-commmon-externsions             # windows
+
+# 创建一份固件工作区
+$ ros2 run micro_ros_setup create_firmware_ws.sh host
+
+# 构建固件
+$ ros2 run micro_ros_setup build_firmware.sh
+$ source install/local_setup.bash
+
+# 创建microros代理
+$ ros2 run micro_ros_setup create_agent_ws.sh
+
+# 构建代理
+$ ros2 run micro_ros_setup build_agent.sh
+$ source install/local_setup.bash
+

完成上述工作后我们micro ros的代理环境就准备就绪了

8.2 以 UDP 方式开启micro_ros 代理

1
+
$ ros2 run micro_ros_agent micro_ros_agent udp4 --port 9999
+

8.3 udp测试流程

这里就不讲详细的配置了,具体过程请看下方链接:

演示视频:[点击此处精准空降: microros_rtt_serial]

9.几点说明

  • 为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本

  • 如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务

  • 如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:

1
+2
+3
+4
+5
+
# 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令
+$ New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow
+
+# 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令
+$ New-NetFirewallRule -DisplayName "WSL" -Direction Outbound -InterfaceAlias "vEthernet (WSL)" -Action Allow
+
  • 如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境

  • 具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89.jpg" new file mode 100644 index 000000000..f0abee8d9 Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89_hu1d41c96ada7dcbd0b71542fef1eff150_4218_250x150_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89_hu1d41c96ada7dcbd0b71542fef1eff150_4218_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..1e3220415 Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.8a576ed4e34311bdaab96c9c7dbbfc89_hu1d41c96ada7dcbd0b71542fef1eff150_4218_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.jpg" new file mode 100644 index 000000000..f0abee8d9 Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_120x120_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..cfadb6438 Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_1600x0_resize_q75_box.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..20d21411f Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_1600x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_800x0_resize_q75_box.jpg" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..5444ae9dd Binary files /dev/null and "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_800x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/index.html" "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/index.html" new file mode 100644 index 000000000..5fa5ba5a2 --- /dev/null +++ "b/p/nxplpc55s69-micropython\347\247\273\346\244\215\346\227\245\345\277\227/index.html" @@ -0,0 +1,37 @@ +【NXP】LPC55S69-Micropython移植日志 +
Featured image of post 【NXP】LPC55S69-Micropython移植日志

【NXP】LPC55S69-Micropython移植日志

本篇文章用于LPC55S69使用Micropython软件包教程

+
+

简单了解Micropython

  • MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。

  • RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。

  • MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。

  • MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。

  • MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。

开发环境

初步移植

首先从RT-Thread官方仓库克隆master分支的仓库到本地

image-20230206105228123

来到该目录:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk,鼠标右键打开ENV工具,首先打开命令行菜单

1
+
menuconfig
+

使能添加Micropython软件包RT-Thread Online Packages--->launage packages--->Micropython

image-20230206110054882

Heap size修改为20480(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)

image-20230206110338978

进入Hardware Module,使能machine uart

image-20230206110701904

同时我们回到主菜单界面,进入Hardware Drives config--->on-chip Peripheral Drivers,使能UART0和UART2

image-20230206110948958

由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面RT-Thread Components--->set main thread stack size修改为8192

image-20230206115128667

保存退出,并使用命令下载软件包:

1
+
pkgs --update
+

image-20230206115308233

使用ENV生成MDK工程:

1
+
scons --target=mdk5
+

image-20230206115527689

BUG修复

双击打开project.uvprojx,进行编译

image-20230206115702684

这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript

image-20230206120429651

切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:

1
+
scons --target=mdk5
+

此时编译错误大大减少,只剩下三个错误:

image-20230206120743700

第一个错误需要在菜单中使能Support legacy version for compatibility(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件

image-20230206111143483

重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明

image-20230206121231129

找到头文件所在位置:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h

image-20230206121521727

此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此PR,所以解决该问题就是重新定义一下DFS_FD_OFFSET

image-20230206121656320

image-20230206122027240

想不到编译之后居然还有一个错误,这里参考这位开发者的issue,将list_mem();注释(此处可能是个官方BUG,后续尝试修复)

image-20230206122146590

image-20230206122748054

最后发现,终于没有错误啦!!!

image-20230206122817350

RT-Thread Micropython环境搭建

VScode扩展搜索下载RT-Thread Micropython

image-20230206123632247

创建工程

vscode下方导航栏点击创建Micropython工程,创建一个新的MicroPython工程,并选择工程存放路径

image-20230206151916502

image-20230206152143031

上电测试Micropython

点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO

image-20230206152315131

测试示例

LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行

image-20230206154101713

Micropython测试

Finsh控制台输入python,转到python控制台,同时还支持quit()exit()命令退回Finsh控制台

image-20230206154310678

简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module

image-20230206160622977

打开图形化菜单进入该路径下:RT-Thread online packages-->launage packages--->system module,使能uos:basic 'operating system' services

同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!

image-20230206162718225

结语

搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!

联系

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91.jpg" new file mode 100644 index 000000000..554c47b8a Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91_hue90c124f4d3c5094341e1772579f0b35_161591_250x150_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91_hue90c124f4d3c5094341e1772579f0b35_161591_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..91cbd0efb Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.0919ae42125356679649ec87a0f76d91_hue90c124f4d3c5094341e1772579f0b35_161591_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.jpg" new file mode 100644 index 000000000..554c47b8a Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_120x120_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..02ebeabf0 Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_1600x0_resize_q75_box.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..09000d699 Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_1600x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_800x0_resize_q75_box.jpg" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..42ad00843 Binary files /dev/null and "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/cover_hue90c124f4d3c5094341e1772579f0b35_161591_800x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/index.html" "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/index.html" new file mode 100644 index 000000000..598fd433a --- /dev/null +++ "b/p/nxplpc55s69_fal\345\210\206\345\214\272\347\256\241\347\220\206\344\270\216easyflash\345\217\230\351\207\217\347\256\241\347\220\206/index.html" @@ -0,0 +1,1576 @@ +【NXP】LPC55S69_FAL分区管理与easyflash变量管理 +
Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理

【NXP】LPC55S69_FAL分区管理与easyflash变量管理

FAL分区管理与easyflash变量管理

+
+

1.FAL组件

1.1什么是FAL

FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:

  • 支持静态可配置的分区表,并可关联多个 Flash 设备;
  • 分区表支持 自动装载 。避免在多固件项目,分区表被多次定义的问题;
  • 代码精简,对操作系统 无依赖 ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;
  • 统一的操作接口。保证了文件系统、OTA、NVM(例如:EasyFlash) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;
  • 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;

image-20230423162047252

通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。

注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。

关于存储,可以用一张图来解释:

image-20230423164134689

来源:ROM、RAM、FLASH、NVM……一文搞定

1.2 使用ENV配置FAL

在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。

我们下面正式讲解FAL组件的使用:

首先打开ENV工具,根据以下路径打开FAL使能RT-Thread Components->[*]FAL: flash abstraction layer,由于我们后面会用到SFUD,所以这里把FAL uses SFUD drivers一并使能,并修改FAL设备名称为W25Q128.

image-20230423164700491

完成上述操作后保存退出,并使用scons --target=mdk5重新生成MDK5文件并打开

1.3 FAL SFUD 移植

为了提供示例,我们选用W25Q128 spi flash作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。

由于目前RT-Thread的SFUD已经对W25Q128 完成支持,根据官方的使用手册,我们仅需编写fal_cfg.h文件完成对FAL_FLASH_DEV_TABLEFAL_PART_TABLE的定义即可。文件存放路径:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
// fal.cfg.h
+
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-21     Wangyuqiang  the first version
+ */
+#ifndef _FAL_CFG_H_
+#define _FAL_CFG_H_
+
+#include <rtthread.h>
+#include <board.h>
+
+#ifndef FAL_USING_NOR_FLASH_DEV_NAME
+#define NOR_FLASH_DEV_NAME             "norflash0"
+#else
+#define NOR_FLASH_DEV_NAME              FAL_USING_NOR_FLASH_DEV_NAME
+#endif
+
+/* Flash device Configuration */
+
+extern struct fal_flash_dev nor_flash0;
+
+/* flash device table */
+
+#define FAL_FLASH_DEV_TABLE                                          \
+{                                                                    \
+    &nor_flash0,                                                     \
+}
+
+/* Partition Configuration */
+
+#ifdef FAL_PART_HAS_TABLE_CFG
+
+/* partition table */
+
+#define FAL_PART_TABLE                                                                                                  \
+{                                                                                                                       \
+    {FAL_PART_MAGIC_WROD,  "easyflash", NOR_FLASH_DEV_NAME,                                    0,       512 * 1024, 0}, \
+    {FAL_PART_MAGIC_WROD,   "download", NOR_FLASH_DEV_NAME,                           512 * 1024,      1024 * 1024, 0}, \
+    {FAL_PART_MAGIC_WROD, "wifi_image", NOR_FLASH_DEV_NAME,                  (512 + 1024) * 1024,       512 * 1024, 0}, \
+    {FAL_PART_MAGIC_WROD,       "font", NOR_FLASH_DEV_NAME,            (512 + 1024 + 512) * 1024,  7 * 1024 * 1024, 0}, \
+    {FAL_PART_MAGIC_WROD, "filesystem", NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024,  7 * 1024 * 1024, 0}, \
+}
+#endif /* FAL_PART_HAS_TABLE_CFG */
+
+#endif /* _FAL_CFG_H_ */
+

此时编译的话是找不到该头文件的,需要我们在Keil中设置:

image-20230423174802203

在RTT FAL组件中的SFUD提供的fal_flash_dev对象默认的nor_flash0参数中,flash大小默认为8M,而W25Q128最大最16M,我们可以选择在.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c文件中对struct fal_flash_dev nor_flash0进行修改:

1
+2
+3
+4
+5
+6
+7
+8
+9
+
struct fal_flash_dev nor_flash0 =
+{
+    .name       = FAL_USING_NOR_FLASH_DEV_NAME,
+    .addr       = 0,
+    .len        = 16 * 1024 * 1024,
+    .blk_size   = 4096,
+    .ops        = {init, read, write, erase},
+    .write_gran = 1
+};
+

当然也可以选择不进行修改,根据大佬的原话就是因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]->ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。

同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径Hardware Drivers Config->On-chip Peripheral Drivers->[*] Enable soft SPI BUS-> [*] Enable soft SPI1 BUS (software simulation),这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。

image-20230423171229953

此时我们回到ENV主界面,进入RT-Thread Components->Device Drivers->Using Serial Flash Universal Driver,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可

image-20230423171646352

到这里,ENV的配置暂时告一段落!

1.4 FAL SFUD 测试用例

为了验证W25Q128及软件模拟spi在SFUD框架上是否能够成功运行,我们在.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\下新建一个soft_spi_flash_init.c文件,代码如下

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-21     Wangyuqiang  the first version
+ */
+
+#include <rtthread.h>
+#include "spi_flash.h"
+#include "spi_flash_sfud.h"
+#include "drv_soft_spi.h"
+#include "drv_pin.h"
+#include "rtconfig.h"
+
+#define cs_pin	GET_PINS(1,9)
+
+static int rt_soft_spi_flash_init(void)
+{
+	int result = -1;
+
+    result = rt_hw_softspi_device_attach("sspi1", "sspi10", cs_pin);
+	rt_kprintf("value is %d\n",result);
+	
+	if(result == RT_EOK)
+	{
+		rt_kprintf("rt_hw_softspi_device_attach successful!\n");
+	}
+
+    if (RT_NULL == rt_sfud_flash_probe("W25Q128", "sspi10"))
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+INIT_COMPONENT_EXPORT(rt_soft_spi_flash_init);
+

这里我们需要指定一个片选引脚,我暂时使用了sspi2的SCK引脚作为片选,这里注意不要同时打开sspi1sspi2,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是sspi1 bussspi10 device,并且挂载flash设备到sspi10

另外我们在.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\下新建fal_sample.c文件,并编写测试代码:

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+
//fal_sample.c
+
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-21     Wangyuqiang  the first version
+ */
+ 
+#include "rtthread.h"
+#include "rtdevice.h"
+#include "board.h"
+#include "fal.h"
+
+#define BUF_SIZE 1024
+
+static int fal_test(const char *partiton_name)
+{
+    int ret;
+    int i, j, len;
+    uint8_t buf[BUF_SIZE];
+    const struct fal_flash_dev *flash_dev = RT_NULL;
+    const struct fal_partition *partition = RT_NULL;
+
+    if (!partiton_name)
+    {
+        rt_kprintf("Input param partition name is null!\n");
+        return -1;
+    }
+
+    partition = fal_partition_find(partiton_name);
+    if (partition == RT_NULL)
+    {
+        rt_kprintf("Find partition (%s) failed!\n", partiton_name);
+        ret = -1;
+        return ret;
+    }
+
+    flash_dev = fal_flash_device_find(partition->flash_name);
+    if (flash_dev == RT_NULL)
+    {
+        rt_kprintf("Find flash device (%s) failed!\n", partition->flash_name);
+        ret = -1;
+        return ret;
+    }
+
+    rt_kprintf("Flash device : %s   "
+               "Flash size : %dK   \n"
+               "Partition : %s   "
+               "Partition size: %dK\n", 
+                partition->flash_name, 
+                flash_dev->len/1024,
+                partition->name,
+                partition->len/1024);
+
+    /* erase all partition */
+    ret = fal_partition_erase_all(partition);
+    if (ret < 0)
+    {
+        rt_kprintf("Partition (%s) erase failed!\n", partition->name);
+        ret = -1;
+        return ret;
+    }
+    rt_kprintf("Erase (%s) partition finish!\n", partiton_name);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0xFF)
+            {
+                rt_kprintf("The erase operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+        i += len;
+    }
+
+    /* write 0x00 to the specified partition */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_write(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) write failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        i += len;
+    }
+    rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", partiton_name, i, i/1024);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0xFF, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0x00)
+            {
+                rt_kprintf("The write operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+
+        i += len;
+    }
+
+    ret = 0;
+    return ret;
+}
+
+static void fal_sample(void)
+{
+    /* 1- init */
+    fal_init();
+
+    if (fal_test("font") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "font");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "font");
+    }
+
+    if (fal_test("download") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "download");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "download");
+    }
+}
+MSH_CMD_EXPORT(fal_sample, fal sample);
+

1.5 测试结果

到这里就可以进行编译下载了,成功后的截图如下:

image-20230423172831146

2.DFS文件系统

2.1 什么是DFS

DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:

image-20230423173347702

在 RT-Thread DFS 中,文件系统有统一的根目录,使用 / 来表示。而在根目录下的 f1.bin 文件则使用 /f1.bin 来表示,2018 目录下的 f1.bin 目录则使用 /data/2018/f1.bin 来表示。即目录的分割符号是 /,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 \ 来作为目录的分割符)。

2.2 DFS架构

RT-Thread DFS 组件的主要功能特点有:

  • 为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。
  • 支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。
  • 支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。

DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。

image-20230423173515014

2.3 使用ENV配置DFS

打开ENV,进入路径RT-Thread Components → DFS: device virtual file system,使能[*] DFS: device virtual file system

image-20230423174113310

由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能RT-Thread Components->[*] Support legacy version for compatibility

image-20230423180859035

由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块W25Q128的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的Maximum sector size需要和W25Q128扇区大小保持一致,修改为4096,路径:RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module

image-20230423181825139

保存退出后使用scons --target=mdk5生成MDK5工程。

2.4 DFS挂载到FAL分区测试

这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。

我们接着修改fal_sample.c文件,修改后代码:

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+
/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-21     Wangyuqiang  the first version
+ */
+ 
+#include "rtthread.h"
+#include "rtdevice.h"
+#include "board.h"
+#include "fal.h"
+
+#include <dfs_posix.h>
+
+#define FS_PARTITION_NAME  "filesystem"
+
+#define BUF_SIZE 1024
+
+static int fal_test(const char *partiton_name)
+{
+    int ret;
+    int i, j, len;
+    uint8_t buf[BUF_SIZE];
+    const struct fal_flash_dev *flash_dev = RT_NULL;
+    const struct fal_partition *partition = RT_NULL;
+
+    if (!partiton_name)
+    {
+        rt_kprintf("Input param partition name is null!\n");
+        return -1;
+    }
+
+    partition = fal_partition_find(partiton_name);
+    if (partition == RT_NULL)
+    {
+        rt_kprintf("Find partition (%s) failed!\n", partiton_name);
+        ret = -1;
+        return ret;
+    }
+
+    flash_dev = fal_flash_device_find(partition->flash_name);
+    if (flash_dev == RT_NULL)
+    {
+        rt_kprintf("Find flash device (%s) failed!\n", partition->flash_name);
+        ret = -1;
+        return ret;
+    }
+
+    rt_kprintf("Flash device : %s   "
+               "Flash size : %dK   \n"
+               "Partition : %s   "
+               "Partition size: %dK\n", 
+                partition->flash_name, 
+                flash_dev->len/1024,
+                partition->name,
+                partition->len/1024);
+
+    /* erase all partition */
+    ret = fal_partition_erase_all(partition);
+    if (ret < 0)
+    {
+        rt_kprintf("Partition (%s) erase failed!\n", partition->name);
+        ret = -1;
+        return ret;
+    }
+    rt_kprintf("Erase (%s) partition finish!\n", partiton_name);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0xFF)
+            {
+                rt_kprintf("The erase operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+        i += len;
+    }
+
+    /* write 0x00 to the specified partition */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_write(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) write failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        i += len;
+    }
+    rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", partiton_name, i, i/1024);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0xFF, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0x00)
+            {
+                rt_kprintf("The write operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+
+        i += len;
+    }
+
+    ret = 0;
+    return ret;
+}
+
+static void fal_sample(void)
+{
+    /* 1- init */
+    fal_init();
+
+    if (fal_test("font") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "font");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "font");
+    }
+
+    if (fal_test("download") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "download");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "download");
+    }
+}
+MSH_CMD_EXPORT(fal_sample, fal sample);
+
+static void fal_elmfat_sample(void)
+{
+    int fd, size;
+    struct statfs elm_stat;
+    struct fal_blk_device *blk_dev;
+    char str[] = "elmfat mount to W25Q flash.", buf[80];
+
+    /* fal init */
+    fal_init();
+
+    /* create block device */
+    blk_dev = (struct fal_blk_device *)fal_blk_device_create(FS_PARTITION_NAME);
+    if(blk_dev == RT_NULL)
+        rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME);
+    else
+        rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
+
+    /* make a elmfat format filesystem */
+    if(dfs_mkfs("elm", FS_PARTITION_NAME) == 0)
+        rt_kprintf("make elmfat filesystem success.\n");
+
+    /* mount elmfat file system to FS_PARTITION_NAME */
+    if(dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0)
+        rt_kprintf("elmfat filesystem mount success.\n");
+
+    /* Get elmfat file system statistics */
+    if(statfs("/", &elm_stat) == 0)
+        rt_kprintf("elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\n", 
+                    elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
+
+    if(mkdir("/user", 0x777) == 0)
+        rt_kprintf("make a directory: '/user'.\n");
+
+    rt_kprintf("Write string '%s' to /user/test.txt.\n", str);
+
+    /* Open the file in create and read-write mode, create the file if it does not exist*/
+    fd = open("/user/test.txt", O_WRONLY | O_CREAT);
+    if (fd >= 0)
+    {
+        if(write(fd, str, sizeof(str)) == sizeof(str))
+            rt_kprintf("Write data done.\n");
+
+        close(fd);   
+    }
+
+    /* Open file in read-only mode */
+    fd = open("/user/test.txt", O_RDONLY);
+    if (fd >= 0)
+    {
+        size = read(fd, buf, sizeof(buf));
+
+        close(fd);
+
+        if(size == sizeof(str))
+            rt_kprintf("Read data from file test.txt(size: %d): %s \n", size, buf);
+    }
+}
+MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample);
+

2.5 测试结果

测试结果如下:

image-20230423182204922

3.Easyflash移植到FAL分区

3.1 简述EasyFlash

关于EasyFlash的来源我们已经讲过了,此处不再赘述。EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。

EasyFlash不仅能够实现对产品的 设定参数运行日志 等信息的掉电保存功能,还封装了简洁的 增加、删除、修改及查询 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。

3.2EasyFlash软件包使用

打开ENV进入路径:RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.,选择软件包版本为最新版。

image-20230423183612019

配置后退出ENV,同时使用pkgs --update下载软件包,然后再使用scons --target=mdk5重新生成MDK5文件

3.3 移植easyflash

下载完easyflash软件包后,我们复制.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c到目录.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c,双击打开该文件,完成以下修改:

  • 1
    +2
    +
    // 修改 FAL_EF_PART_NAME 为 easyflash
    +#define FAL_EF_PART_NAME               "easyflash"
    +
  • 1
    +2
    +3
    +4
    +
    // 修改环境变量内容为 {"boot_times", "0"},这里我们先只设置一个开机次数
    +static const ef_env default_env_set[] = {
    +        {"boot_times", "0"},
    +};
    +

3.4 编写Easyflash测试用例

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+
/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-21     Wangyuqiang  the first version
+ */
+ 
+#include "rtthread.h"
+#include "rtdevice.h"
+#include "board.h"
+#include "fal.h"
+
+#include <dfs_posix.h>
+
+#include "easyflash.h"
+#include <stdlib.h>
+
+#define FS_PARTITION_NAME  "filesystem"
+
+#define BUF_SIZE 1024
+
+static int fal_test(const char *partiton_name)
+{
+    int ret;
+    int i, j, len;
+    uint8_t buf[BUF_SIZE];
+    const struct fal_flash_dev *flash_dev = RT_NULL;
+    const struct fal_partition *partition = RT_NULL;
+
+    if (!partiton_name)
+    {
+        rt_kprintf("Input param partition name is null!\n");
+        return -1;
+    }
+
+    partition = fal_partition_find(partiton_name);
+    if (partition == RT_NULL)
+    {
+        rt_kprintf("Find partition (%s) failed!\n", partiton_name);
+        ret = -1;
+        return ret;
+    }
+
+    flash_dev = fal_flash_device_find(partition->flash_name);
+    if (flash_dev == RT_NULL)
+    {
+        rt_kprintf("Find flash device (%s) failed!\n", partition->flash_name);
+        ret = -1;
+        return ret;
+    }
+
+    rt_kprintf("Flash device : %s   "
+               "Flash size : %dK   \n"
+               "Partition : %s   "
+               "Partition size: %dK\n", 
+                partition->flash_name, 
+                flash_dev->len/1024,
+                partition->name,
+                partition->len/1024);
+
+    /* erase all partition */
+    ret = fal_partition_erase_all(partition);
+    if (ret < 0)
+    {
+        rt_kprintf("Partition (%s) erase failed!\n", partition->name);
+        ret = -1;
+        return ret;
+    }
+    rt_kprintf("Erase (%s) partition finish!\n", partiton_name);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0xFF)
+            {
+                rt_kprintf("The erase operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+        i += len;
+    }
+
+    /* write 0x00 to the specified partition */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0x00, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_write(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) write failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        i += len;
+    }
+    rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", partiton_name, i, i/1024);
+
+    /* read the specified partition and check data */
+    for (i = 0; i < partition->len;)
+    {
+        rt_memset(buf, 0xFF, BUF_SIZE);
+
+        len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
+
+        ret = fal_partition_read(partition, i, buf, len);
+        if (ret < 0)
+        {
+            rt_kprintf("Partition (%s) read failed!\n", partition->name);
+            ret = -1;
+            return ret;
+        }
+
+        for(j = 0; j < len; j++)
+        {
+            if (buf[j] != 0x00)
+            {
+                rt_kprintf("The write operation did not really succeed!\n");
+                ret = -1;
+                return ret;
+            }
+        }
+
+        i += len;
+    }
+
+    ret = 0;
+    return ret;
+}
+
+static void fal_sample(void)
+{
+    /* 1- init */
+    fal_init();
+
+    if (fal_test("font") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "font");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "font");
+    }
+
+    if (fal_test("download") == 0)
+    {
+        rt_kprintf("Fal partition (%s) test success!\n", "download");
+    }
+    else
+    {
+        rt_kprintf("Fal partition (%s) test failed!\n", "download");
+    }
+}
+MSH_CMD_EXPORT(fal_sample, fal sample);
+
+static void fal_elmfat_sample(void)
+{
+    int fd, size;
+    struct statfs elm_stat;
+    struct fal_blk_device *blk_dev;
+    char str[] = "elmfat mount to W25Q flash.", buf[80];
+
+    /* fal init */
+    fal_init();
+
+    /* create block device */
+    blk_dev = (struct fal_blk_device *)fal_blk_device_create(FS_PARTITION_NAME);
+    if(blk_dev == RT_NULL)
+        rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME);
+    else
+        rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
+
+    /* make a elmfat format filesystem */
+    if(dfs_mkfs("elm", FS_PARTITION_NAME) == 0)
+        rt_kprintf("make elmfat filesystem success.\n");
+
+    /* mount elmfat file system to FS_PARTITION_NAME */
+    if(dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0)
+        rt_kprintf("elmfat filesystem mount success.\n");
+
+    /* Get elmfat file system statistics */
+    if(statfs("/", &elm_stat) == 0)
+        rt_kprintf("elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\n", 
+                    elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
+
+    if(mkdir("/user", 0x777) == 0)
+        rt_kprintf("make a directory: '/user'.\n");
+
+    rt_kprintf("Write string '%s' to /user/test.txt.\n", str);
+
+    /* Open the file in create and read-write mode, create the file if it does not exist*/
+    fd = open("/user/test.txt", O_WRONLY | O_CREAT);
+    if (fd >= 0)
+    {
+        if(write(fd, str, sizeof(str)) == sizeof(str))
+            rt_kprintf("Write data done.\n");
+
+        close(fd);   
+    }
+
+    /* Open file in read-only mode */
+    fd = open("/user/test.txt", O_RDONLY);
+    if (fd >= 0)
+    {
+        size = read(fd, buf, sizeof(buf));
+
+        close(fd);
+
+        if(size == sizeof(str))
+            rt_kprintf("Read data from file test.txt(size: %d): %s \n", size, buf);
+    }
+}
+MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample);
+
+static void easyflash_sample(void)
+{
+    /* fal init */
+    fal_init();
+
+    /* easyflash init */
+    if(easyflash_init() == EF_NO_ERR)
+    {
+        uint32_t i_boot_times = NULL;
+        char *c_old_boot_times, c_new_boot_times[11] = {0};
+
+        /* get the boot count number from Env */
+        c_old_boot_times = ef_get_env("boot_times");
+        /* get the boot count number failed */
+        if (c_old_boot_times == RT_NULL)
+            c_old_boot_times[0] = '0';
+
+        i_boot_times = atol(c_old_boot_times);
+        /* boot count +1 */
+        i_boot_times ++;
+        rt_kprintf("===============================================\n");
+        rt_kprintf("The system now boot %d times\n", i_boot_times);
+        rt_kprintf("===============================================\n");
+        /* interger to string */
+        sprintf(c_new_boot_times, "%d", i_boot_times);
+        /* set and store the boot count number to Env */
+        ef_set_env("boot_times", c_new_boot_times);
+        ef_save_env();
+    }
+}
+MSH_CMD_EXPORT(easyflash_sample, easyflash sample);
+

3.5 测试结果

打开串口助手,输入命令:

1
+
msh />easyflash_sample
+

第一次命令调用:

image-20230423185619472

第二次RESET开发板后调用:

image-20230423185703046

4.结语

至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!

5.联系

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3.jpg" new file mode 100644 index 000000000..dd3feb44c Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3_hu31f054e617ccf5275f397086d95972c2_413191_250x150_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3_hu31f054e617ccf5275f397086d95972c2_413191_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..b4358df4b Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.89fd4331b6d80ee0bfb4d6ca368a09f3_hu31f054e617ccf5275f397086d95972c2_413191_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.jpg" new file mode 100644 index 000000000..dd3feb44c Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_120x120_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..01a765651 Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_1600x0_resize_q75_box.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f1991bc3a Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_1600x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_800x0_resize_q75_box.jpg" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..bff4a7a57 Binary files /dev/null and "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/cover_hu31f054e617ccf5275f397086d95972c2_413191_800x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/index.html" "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/index.html" new file mode 100644 index 000000000..7d19592d1 --- /dev/null +++ "b/p/nxplpc55s69\345\210\235\344\270\212\346\211\213/index.html" @@ -0,0 +1,29 @@ +【NXP】LPC55S69初上手 +
Featured image of post 【NXP】LPC55S69初上手

【NXP】LPC55S69初上手

前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。

+
+

前言

前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。

开始测试

首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk,首先使用RT-Thread的ENV工具生成MDK工程:

1
+
scons --target=mdk5
+

image-20230205113527665

这里建议大家使用最新版ENV工具。然后双击打开project.uvprojx工程,点击重新编译。

image-20230205113758912

但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。

6d869b905839641fa60aadb8d2a6a9d

dd1f984d7543997e5fa6fa50aee36c7

BUG分析与解决

首先先看一下我的keil版本为V5.25:

4b368869fbf8077591b20eccbd05ef8

听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)

此处附上Keil最新版下载官网

下载好最新版本后,前面的步骤重复,然后重新编译下载即可。

项目演示

下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:

video

结语

本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。

联系

+Licensed under CC BY-NC-SA 4.0
+Last updated on Feb 05, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548.jpg" new file mode 100644 index 000000000..a424544ae Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548_hu63ed3deabe1b375a8669082d0efcf2de_379910_250x150_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548_hu63ed3deabe1b375a8669082d0efcf2de_379910_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..719f1b3d3 Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.e0e66e26d71581d2a372ce183b076548_hu63ed3deabe1b375a8669082d0efcf2de_379910_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" new file mode 100644 index 000000000..a424544ae Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_120x120_fill_q75_box_smart1.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..8a375fb2b Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_1600x0_resize_q75_box.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c4f9266ec Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_1600x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_800x0_resize_q75_box.jpg" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..d4a3e14ef Binary files /dev/null and "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_800x0_resize_q75_box.jpg" differ diff --git "a/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" new file mode 100644 index 000000000..8301e2035 --- /dev/null +++ "b/p/nxplpc55s69\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272/index.html" @@ -0,0 +1,27 @@ +【NXP】LPC55S69开发环境搭建 +
Featured image of post 【NXP】LPC55S69开发环境搭建

【NXP】LPC55S69开发环境搭建

本篇文章用于LPC55S69开发环境及配置工具的使用教学

+
+

前期准备

资料:

开发环境(官方直链)

MCUXpresso Config ToolsMCUXpresso IDE的安装不再赘述,下面是SDK代码包的安装教学

1.选择开发板–>

image-20230205133247352

2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)

image-20230205133458266

3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击下载SDK

img-202302031122007

4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包

image-20230204102200685

5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载

IDE配置

完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开MCUXpresso IDE,在主界面的下方栏可以看到有一个Installed SDKs,准备好刚刚下载的SDK代码包,导入其中

image-20230204105301726

之后我们就可以使用这个SDK代码包去创建一个新的工程了。

工程导入

这里我们简单做个示范,选择导入示例工程

image-20230204105601052

选择指定的开发板后点击下一步

image-20230204110547819

image-20230204110900541

在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可

image-20230204111200845

工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译

image-20230204111519951

image-20230204111803236

MCUXpresso IDE有两个地方都可以启动调试,选择一个习惯的即可

image-20230204112026675

配置工具使用

MCUXpresso IDE配套的还有MCUXpresso Config Tools,打开MCUXpresso IDE,找到配置工具按钮打开

image-20230204113350126

image-20230204113817301

结语

到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!

联系

+Licensed under CC BY-NC-SA 4.0
+Last updated on Feb 04, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee.jpg" new file mode 100644 index 000000000..db75535ce Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_250x150_fill_q75_box_smart1.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..8707cd19e Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.bdbd7b056e1588e5208abd037b3cd2ee_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.jpg" new file mode 100644 index 000000000..db75535ce Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_120x120_fill_q75_box_smart1.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d6aa15a22 Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_1600x0_resize_q75_box.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ddcfffab6 Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_1600x0_resize_q75_box.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_800x0_resize_q75_box.jpg" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..11c2317c4 Binary files /dev/null and "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_800x0_resize_q75_box.jpg" differ diff --git "a/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/index.html" "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/index.html" new file mode 100644 index 000000000..67e5ce458 --- /dev/null +++ "b/p/rdc-2022\347\272\252\345\277\265\347\211\210\345\274\200\345\217\221\346\235\277-d1s\345\234\250rt-smart\350\277\220\350\241\214/index.html" @@ -0,0 +1,56 @@ +RDC 2022纪念版开发板-D1S在RT-Smart运行 +
Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行

RDC 2022纪念版开发板-D1S在RT-Smart运行

近日在RT-Thread举办的RDC开发者大会上抽奖获得的全志D1S开发板,这段时间也是借此来简单做个小测试。

+
+

开发环境

软件

  • ubuntu20.04
  • VMware Workstation

硬件

  • RDC2022纪念版开发板
  • 全志D1s芯片

材料下载

首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。

1
+
git clone https://github.com/RT-Thread/userapps.git
+

image-20230119110742488

userapps目录下克隆RT-Thread仓库代码

1
+
git clone https://github.com/RT-Thread/rt-thread.git
+

image-20230119110934253

Riscv工具链配置

进入userapps/tools,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到 userapps\tools\gun_gcc 目录。

1
+
python3 get_toolchain.py riscv64
+

image-20230119111856993

返回上一级,刷新工具链环境,同时记住这里的EXEC_PATH工具链路径,后面需要修改为此路径

1
+2
+
cd ..
+source smart-env.sh riscv64
+

image-20230119111552268

内核环境编译

scons安装

环境编译会用到scons,所以我们先下载scons

1
+
sudo apt install scons
+

查看scons版本信息可判断是否安装成功

image-20230119112101897

env工具安装

依次执行以下程序:

1
+2
+3
+
scons --menuconfig
+source ~/.env/env.sh
+pkgs --update
+

内核编译

使用 scons 命令进行编译,编译成功后会在 userapps/rt-thread/bsp/allwinner/d1s 目录下生成 sd.bin,这个文件就是我们需要烧录到开发板中的文件,它包括了 uboot.dtb,opensbi,rtthread.bin

1
+
scons
+

此时直接编译会报错,因为工具链路径还没有修改

image-20230119112916923

我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径

image-20230119113207832

再次执行scons命令编译

image-20230119113353060

程序烧录

我这里采用的是从TF卡作为启动方式。

1、首先准备一张容量在128G的空白TF卡

2、格式化TF卡,并使用ubuntu的gparted工具重新分区

如果没有下载该工具可使用下面的命令进行下载:

1
+
sudo apt install gparted
+

启动该工具

1
+
sudo gparted
+

这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32

image-20230119114019113

3、接下来进行程序的烧录

首先进入userapps/rt-thread/bsp/allwinner/d1s/tools,执行命令:

1
+
sudo dd if=boot0_sdcard_sun20iw1p1_d1s.bin of=/dev/sdb bs=1024 seek=8
+

image-20230119114457823

返回上一级,再次执行命令:

1
+
sudo dd if=sd.bin of=/dev/sdb bs=1024 seek=56
+

image-20230119114605503

到此烧录工作已完成。

启动RT-Smart

我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。

此处注意串口波特率为500000

image-20230119115334091

简单测试下MSH命令:

image-20230119115950076

到此就测试结束啦,欢迎大家讨论交流。

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover.jpg" "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover.jpg" differ diff --git "a/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/index.html" "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/index.html" new file mode 100644 index 000000000..2d7ba56c9 --- /dev/null +++ "b/p/ubuntu\345\275\273\345\272\225\345\210\240\351\231\244\351\200\232\350\277\207apt\346\226\271\345\274\217\345\256\211\350\243\205\347\232\204\347\250\213\345\272\217/index.html" @@ -0,0 +1,41 @@ +ubuntu彻底删除通过apt方式安装的程序 +
Featured image of post ubuntu彻底删除通过apt方式安装的程序

ubuntu彻底删除通过apt方式安装的程序

ubuntu彻底删除通过apt方式安装的程序

+
+

以删除apache2为例,其它程序也都是这么删…
1.先通过apt删除程序和相关配置文件

1
+
sudo apt-get --purge remove apache2
+

2.自动删除不使用的软件包

1
+
sudo apt-get autoremove
+

3.找出与apache2相关的程序

1
+
dpkg --get-selections|grep apache2
+

没有就不显示,如果有就删除这些相关的程序

1
+
sudo apt-get --purge remove xxx
+

4.查看apache2是否还有进程存在

1
+
ps -ef |grep apache2
+

如果有就杀掉

1
+
sudo kill -9 8888 //后面接pid号码,用空格隔开
+

5.全局查找和apache2相关的文件,需要一定时间,稍等

1
+
sudo find / -name apache2*
+

将找到的文件逐个删掉

1
+
sudo rm -rf /usr/share/bash-completion/completions/apache2ctl
+

这样就彻底删除掉apache2了

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 16, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover.jpg" "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover.jpg" differ diff --git "a/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/index.html" "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/index.html" new file mode 100644 index 000000000..51a6b231c --- /dev/null +++ "b/p/ubuntu\346\241\214\351\235\242\346\201\242\345\244\21520.04/index.html" @@ -0,0 +1,55 @@ +ubuntu桌面恢复(20.04) +
Featured image of post ubuntu桌面恢复(20.04)

ubuntu桌面恢复(20.04)

恢复ubuntu20.04默认桌面管理器

+
+

恢复ubuntu20.04默认桌面管理器

起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能远程控制桌面了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(gnome图形管理器)也变成了我不喜欢的风格(轻量级的LightDM)了,大家以后要慎重。
注意:我是个半吊子,仅供参考。

一、GDM, KDM, LightDM, SDDM的区别和安装配置

GDM, KDM, LightDM, SDDM的区别和安装配置
gdm3,kdm 和 lightdm 都是显示管理器。 它们提供图形化登录并处理用户身份验证。

1、GDM,gnome系列的图形管理器

1
+
sudo apt-get install gdm3
+
1
+
sudo apt-get remove gdm3
+

2、KDM,SDDM是KDE系列的图形管理器

kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。

1
+
sudo apt-get install sddm 
+
1
+
sudo apt-get remove sddm
+

3、LightDM

LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。

1
+
sudo apt-get install lightdm
+
1
+
sudo apt-get remove lightdm
+

二、配置和切换

1
+
sudo dpkg-reconfigure gdm3
+

你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。

要检查当前正在使用的显示管理器,请运行以下命令:

1
+
cat /etc/X11/default-display-manager
+

Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:

1
+
sudo dpkg-reconfigure lightdm
+

Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:

1
+
sudo dpkg-reconfigure lightdm
+

GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。

三、恢复ubuntu20.04默认桌面管理器

恢复ubuntu20.04默认桌面管理器
目前Ubuntu的主流桌面GNOME, Ubntu的内置桌面是Untiy

1、打开终端,用管理员口令下载相关资源

1
+
Ctrl+Alt+T
+

打开终端,用管理员口令下载相关资源

2、安装gnome-shell

1
+
sudo apt-get install gnome-shell
+

提示:

管理员权限需要输入密码,但是系统不会显示你输入的密码
输入完成后,直接回车即可

3、安装ubuntu-gnome-desktop

1
+
sudo apt-get install ubuntu-gnome-desktop
+

4、安装unity-tweak-tool和gnome-tweak-tool

1
+
sudo apt-get install unity-tweak-tool
+
1
+
sudo apt-get install gnome-tweak-tool
+

5、安装完成后重启

然后一切恢复如初,仿佛没发生过。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 14, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover.jpg" "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover.jpg" new file mode 100644 index 000000000..3237d98e6 Binary files /dev/null and "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover.jpg" differ diff --git "a/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..eb235dd1e Binary files /dev/null and "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ea6c63128 Binary files /dev/null and "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_1600x0_resize_q75_box.jpg" differ diff --git "a/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a02ddabfa Binary files /dev/null and "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_800x0_resize_q75_box.jpg" differ diff --git "a/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/index.html" "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/index.html" new file mode 100644 index 000000000..bf5d9e4f3 --- /dev/null +++ "b/p/x11vnc\345\256\211\350\243\205\344\270\216\351\205\215\347\275\256/index.html" @@ -0,0 +1,117 @@ +x11vnc安装与配置 +
Featured image of post x11vnc安装与配置

x11vnc安装与配置

最近学校在做ros使用树莓派做一个路径规划,但是一般的vncserver无法使用rviz可视化工具,所以选择了x11vnc这款工具。

+
+

1. 安装x11vnc

1
+
sudo apt-get install x11vnc -y
+

直接安装成功。

2. 设置vnc密码

密码存储在/etc/目录里面

1
+
sudo x11vnc -storepasswd /etc/x11vnc.pass
+

放在这个位置,需要设置文件读取权限
否则会提示密码校验失败

1
+
sudo chmod 777 /etc/x11vnc.pass
+

3.创建vnc配置文件

在/etc/init 下创建一个x11vnc.conf的文件

1
+2
+
 cd /etc/init 
+ sudo gedit x11vnc.conf
+

文件内容如下:

1
+2
+3
+4
+5
+6
+
#description "xiaoqiang vnc server"
+#start on runlevel [2345]
+#stop on runlevel [06]
+#script
+    exec /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport 5900 -shared
+#end script
+

我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。

4.启动vnc服务

1
+
source /etc/init/x11vnc.conf
+

在这里插入图片描述
启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了

5.设置自启动

我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。

(1)首先编写一个脚本

1
+
gedit x11vnc.sh
+

添加以下内容
第一行是要添加的解释器,后面是要执行的指令内容

1
+2
+
#!/bin/bash
+source /etc/init/x11vnc.conf
+

防止误删,从home移动到/etc/init.d/文件夹中
并添加权限

1
+2
+
sudo mv x11vnc.sh /etc/init.d/
+sudo chmod 777 /etc/init.d/x11vnc.sh
+

(2)添加启动项

点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。
在这里插入图片描述
点击右侧添加,添加自动启动项。
在这里插入图片描述
添加内容如下;重要的是第二行,

1
+
bash /etc/init.d/x11vnc.sh
+

用bash启动才能成功,保存之后重启,确实可以开机自启了。
在这里插入图片描述

6.x11vnc配置(安装虚拟显卡驱动)

如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示

(1)首先还是安装命令

1
+
sudo apt-get install xserver-xorg-video-dummy
+

(2)接下来就是创建配置文件 /etc/X11/xorg.conf

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
Section "Device"
+    Identifier  "Dummy"
+    Driver      "dummy"
+    VideoRam    64000
+    Option      "IgnoreEDID"    "true"
+    Option      "NoDDC" "true"
+EndSection
+
+Section "Monitor"
+    Identifier  "Monitor"
+    HorizSync   15.0-100.0
+    VertRefresh 15.0-200.0
+EndSection
+
+Section "Screen"
+    Identifier  "Screen"
+    Monitor     "Monitor"
+    Device      "Dummy"
+    DefaultDepth    24
+    SubSection  "Display"
+        Depth   24
+        Modes   "1280x720"
+    EndSubSection
+EndSection
+

(3)再修改个文件加点配置

1
+
vi /boot/firmware/usercfg.txt
+
1
+2
+
framebuffer_width=1280
+framebuffer_height=720
+

如果想要恢复显示器的连接,可以先使用ssh访问终端并将/etc/X11/xorg.conf这个文件删除,再次重启即可

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 14, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover.jpg" "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover.jpg" new file mode 100644 index 000000000..dbeeb4d28 Binary files /dev/null and "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover.jpg" differ diff --git "a/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d719c79aa Binary files /dev/null and "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..13a3a8c42 Binary files /dev/null and "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ccfb1917a Binary files /dev/null and "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_800x0_resize_q75_box.jpg" differ diff --git "a/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/index.html" "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/index.html" new file mode 100644 index 000000000..c23862daf --- /dev/null +++ "b/p/\345\265\214\345\205\245\345\274\217\347\264\240\345\205\273\346\217\220\345\215\207mpu\344\270\216mcu/index.html" @@ -0,0 +1,26 @@ +【嵌入式素养提升】MPU与MCU +
Featured image of post 【嵌入式素养提升】MPU与MCU

【嵌入式素养提升】MPU与MCU

计算、控制单元小型化后出现的技术,集成电路进步带来的计算机系统集成程度提高的结果。

+
+

MPU与MCU

MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。

但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。

在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。

由于主要完成“控制”相关的任务,所以称为 Controller。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。

Processor,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。

以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。

为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。

从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。

总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Nov 04, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" new file mode 100644 index 000000000..5e0a7aa05 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..6fe547949 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.jpg" new file mode 100644 index 000000000..5e0a7aa05 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..60b2c6b62 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..3672f81d1 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..dac155031 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/index.html" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/index.html" new file mode 100644 index 000000000..2192aba9a --- /dev/null +++ "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\344\277\241\345\217\267\351\207\217\345\217\212pv\346\223\215\344\275\234\350\257\246\350\247\243/index.html" @@ -0,0 +1,80 @@ +信号量及PV操作详解 +
Featured image of post 信号量及PV操作详解

信号量及PV操作详解

无论是大部分的教材上的信号量,还是博客中的信号量,基本上解说都是类似下面这种,给出几个不同的信号量种类然后加一点说明,完全不能理解信号量的PV操作。本文基于此对信号量进行详细叙述,希望能对你有所帮助!

+
+

信号量

  • 一个特殊变量
  • 用于进程间传递信息的一个整数值

定义如下:

1
+2
+3
+4
+5
+
struct semaphore
+{
+	int count;
+	quenue Type quenue;
+}
+
  • 信号量说明:semaphore s;
  • 对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen))

P、V操作定义

P(s)

1
+2
+3
+4
+5
+6
+7
+8
+9
+
{
+	s.count --; //信号量值减一
+	if(s.count<0)
+	{
+		该进程状态置为阻塞态;
+		将该进程插入相应的等待队列s.quenue末尾;
+		重新调度
+	}
+}
+

down,semwait:也代表P操作

V(s)

1
+2
+3
+4
+5
+6
+7
+8
+
{
+	s.ount++;
+	if(s.count<=0)
+	{
+	唤醒相应等待队列s.queue中等待的一个进程;
+	改变其状态为就绪态,并将其插入就绪队列;
+	}
+}
+

up,semsignal:也代表V操作

相关说明

  • P,V操作为原语操作
  • 在信号量上定义了三个操作 +初始化(非负数)、P操作、V操作
  • 最初提出的是二元信号量(解决互斥) +之后,推广到一般信号量(多值)或技术信号量(解决同步)

用PV操作解决进程间互斥问题

  • 分析并发进程的关键活动,划定临界区
  • 设置信号量mutux,初值为1
  • 在临界区前实施P(mutux)
  • 在临界区之后实施V(mutux)

图片演示

相关解释:

  • 临界区 : 我们把并发进程中与共享变量有关的程序段称为临界区。

  • 信号量 : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。

  • 进程的互斥:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。

  • 进程的同步:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。

  • pv操作又称wait,signal原语。 +主要是操作进程中对进程控制的信息量的加减控制。

注意:在霍尔管程中,wait操作signal操作用于被设计为两个可以中断的过程,而非原语。 +在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 +条件变量的两种操作:

  • wait()操作[阻塞调用进程]
  • signal()操作[释放/唤醒在条件变量上阻塞的进程]
  • wait用法: +wait(num),num是目标参数,wait的作用是使其(信息量)减一。 +如果信息量>=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 +signal用法: +signal(num),num是目标参数,signal的作用是使其(信息量)加一。 +如果信息量>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。

本文资源来自Operating Systems +参考:操作系统P,V(wait,signal原语)操作讲解

+Licensed under CC BY-NC-SA 4.0
+Last updated on Mar 10, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" new file mode 100644 index 000000000..5e0a7aa05 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..6fe547949 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.0ba7e958c5c56076b5d8231f276a622f_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.jpg" new file mode 100644 index 000000000..5e0a7aa05 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..60b2c6b62 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..3672f81d1 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..dac155031 Binary files /dev/null and "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/index.html" "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/index.html" new file mode 100644 index 000000000..d6995cf9a --- /dev/null +++ "b/p/\346\223\215\344\275\234\347\263\273\347\273\237\350\277\233\347\250\213\344\270\212\344\270\213\346\226\207\345\222\214\347\272\277\347\250\213\344\270\212\344\270\213\346\226\207/index.html" @@ -0,0 +1,33 @@ +进程上下文和线程上下文 +
Featured image of post 进程上下文和线程上下文

进程上下文和线程上下文

在操作系统的学习中,我们经常会遇到诸如进程、线程、进程上下文和线程上下文等语义,但具体是什么意思,相信大家也时常被绕晕。今天就具体讲解一下关于进程、线程及一些相关术语的解释。

+
+

进程

操作系统资源分配的基本单位,也就是指计算机中已执行的程序。

  • 在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,进程是程序的基本执行实体;
  • 在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是线程的容器。
  • 程序本身只是指令、数据及其组织形式的描述,相当于一个名词,进程才是程序(那些指令和数据)的真正执行实例.

进程上下文

进程上下文就是表示进程信息的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。

Linux进程举例: +—-进程的运行环境主要包括:

1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 +2.环境变量:提供进程运行所需的环境信息。 +3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 +4.进程访问设备或者文件时的权限。 +5.各种硬件寄存器。 +6.地址转换信息。

由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。

线程

操作系统能够进行运算调度的最小单位

  • 大部分情况下,它被包含在进程之中,是进程中的实际运作单位。
  • 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
  • 线程是独立调度和分派的基本单位。 +线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。
  • 同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。

线程上下文

进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。同样的,线程也有上下文。

当线程被抢占时,就会发生线程之间的上下文切换。 +如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。

线程上下文与进程上下文对比

上下文内容进程线程
指向可执行文件的指针×
××
内存(数据段和堆)×
状态××
优先级××
程序IO的状态×
授予权限×
调度信息×
审计信息×
文件描述符×
文件读/写指针×
寄存器组××
+Licensed under CC BY-NC-SA 4.0
+Last updated on Mar 08, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3.jpg" new file mode 100644 index 000000000..80029fe06 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3_hu0ba98275d6445c79f820f07c37ff307c_145062_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3_hu0ba98275d6445c79f820f07c37ff307c_145062_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..881cdec16 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.040e5e7d6e88d7e610a8a21b7b4b70c3_hu0ba98275d6445c79f820f07c37ff307c_145062_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.jpg" new file mode 100644 index 000000000..80029fe06 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..b27c91311 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..dd8bedf06 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f5c2b5920 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/index.html" new file mode 100644 index 000000000..c20d14bd5 --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2501\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-\344\270\244\346\225\260\344\272\244\351\233\206-\345\277\253\344\271\220\346\225\260-\344\270\244\346\225\260\344\271\213\345\222\214/index.html" @@ -0,0 +1,276 @@ +【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和 +
Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和

【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和

算法任务:哈希表理论基础、leetcode242.有效的字母异位词、leetcode349.两个数组的交集、leetcode1.两数之和

+
+

今日任务

  • 哈希表理论基础

  • 242.有效的字母异位词

  • 349.两个数组的交集

  • 202.快乐数

  • 1.两数之和

1.哈希表理论基础

(1)哈希表

哈希表(Hash table,国内也有一些书籍翻译为散列表):是根据关键码的值而直接访问的数据结构。

最常见的哈希表例子就是数组。

哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:

image-20230220102916613

那么哈希表一般适用于哪些场景呢?一般哈希表都是用来快速判断一个元素是否出现在集合里。

例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。

我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。

这里将商品列表映射到哈希表上就涉及到哈希函数(Hash function)

(2)哈希函数

哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。

哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。

image-20230220105717329

此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?

为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。

此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。

这时候就需要引入哈希碰撞了。

(3)哈希碰撞

如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为哈希碰撞

image-20230220112851251

对于哈希碰撞一般有两种解决方法:链地址法(拉链法)和线性探测法

(4)链地址法(拉链法)

这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了

image-20230220113841529

(5)线性探测法

使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。

例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。

image-20230220114854813

此外对于哈希碰撞的常用解决方法还有开放定址法、再哈希法、建立公共溢出区等等…

(6)常见的三种哈希结构

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:

  • 数组
  • set(集合)
  • map(映射)

数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):

set(集合)

在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:

集合底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::set红黑树有序O(log n)O(log n)
std::multiset红黑树有序O(logn)O(logn)
std::unordered_set哈希表无序O(1)O(1)

map(映射)

映射底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::map红黑树key有序key不可重复key不可修改O(logn)O(logn)
std::multimap红黑树key有序key可重复key不可修改O(log n)O(log n)
std::unordered_map哈希表key无序key不可重复key不可修改O(1)O(1)

(7)总结

当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。

但是哈希法的缺点也显而易见的:牺牲空间去换取时间

2.Leetcode242.有效的字母异位词

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram

(1)题目

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

1
+2
+
输入: s = "anagram", t = "nagaram"
+输出: true
+

示例 2:

1
+2
+
输入: s = "rat", t = "car"
+输出: false
+

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • s 和 t 仅包含小写字母

进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

(2)思路

前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。

由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.

例如,我们对字符串s = “aee”, t = ‘“eae”,我们观察动画:

242.有效的字母异位词

我们定义一个record的数组来记录字符串s里所有字符出现的次数。

需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。

在遍历字符串s的时候,只需要将s[i] = ‘a’所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.

最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。

时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
class Solution {
+public:
+    bool isAnagram(string s, string t) {
+        int record[26] = {0};
+        for (int i = 0; i < s.size(); i++) {
+            // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
+            record[s[i] - 'a']++;
+        }
+        for (int i = 0; i < t.size(); i++) {
+            record[t[i] - 'a']--;
+        }
+        for (int i = 0; i < 26; i++) {
+            if (record[i] != 0) {
+                // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
+                return false;
+            }
+        }
+        // record数组所有元素都为零0,说明字符串s和t是字母异位词
+        return true;
+    }
+};
+

3.Leetcode349. 两个数组的交集

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays

(1)题目

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

1
+2
+
输入:nums1 = [1,2,2,1], nums2 = [2,2]
+输出:[2]
+

示例 2:

1
+2
+3
+
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
+输出:[9,4]
+解释:[4,9] 也是可通过的
+

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

(2)思路

在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:

image-20230220175039323

题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。

之所以这里不使用数组,是因为题目限制了数组的大小,并且如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。

所以结合std::unordered_set的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set

image-20230220180154535

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
class Solution {
+public:
+    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
+        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
+        unordered_set<int> nums_set(nums1.begin(), nums1.end());// 定义哈希表存放结果
+        for (int num : nums2) {
+            // 发现nums2的元素 在nums_set里又出现过
+            if (nums_set.find(num) != nums_set.end()) { // 在nums1中查找num(nums2)
+                result_set.insert(num);// 如果发现与nums(nums2)的元素,向result_set插入该元素
+            }
+        }
+        return vector<int>(result_set.begin(), result_set.end());
+    }
+};
+

当然这道题也可以使用数组的方式进行求解:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+
class Solution {
+public:
+    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
+        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
+        int hash[1005] = {0}; // 默认数值为0
+        for (int num : nums1) { // nums1中出现的字母在hash数组中做记录
+            hash[num] = 1;
+        }
+        for (int num : nums2) { // nums2中出现话,result记录
+            if (hash[num] == 1) {
+                result_set.insert(num);
+            }
+        }
+        return vector<int>(result_set.begin(), result_set.end());
+    }
+};
+

4.Leetcode202.快乐数

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number

(1)题目

编写一个算法来判断一个数 n 是不是快乐数。

**「快乐数」 **定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。

  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。

  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

1
+2
+3
+4
+5
+6
+7
+
输入:n = 19
+输出:true
+解释:
+12 + 92 = 82
+82 + 22 = 68
+62 + 82 = 100
+12 + 02 + 02 = 1
+

示例 2:

1
+2
+
输入:n = 2
+输出:false
+

提示:

  • 1 <= n <= 231 - 1

(2)思路

根据题目所给出的提示:重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。

简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?

那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+
class Solution {
+public:
+    // 取数值各个位上的单数平方之和
+    int getSum(int n) {
+        int sum = 0;
+        while (n) {
+            sum += (n % 10) * (n % 10); // n每位数的平方和
+            n /= 10;
+        }
+        return sum;
+    }
+    bool isHappy(int n) {
+        unordered_set<int> set;
+        while(1) {
+            int sum = getSum(n);
+            if (sum == 1) {
+                return true;
+            }
+            // 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
+            if (set.find(sum) != set.end()) {
+                return false;
+            } else {
+                set.insert(sum); // 记录第一次出现的数
+            }
+            n = sum;
+        }
+    }
+};
+

5.Leetcode1.两数之和

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum

(1)题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

1
+2
+3
+
输入:nums = [2,7,11,15], target = 9
+输出:[0,1]
+解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 
+

示例 2:

1
+2
+
输入:nums = [3,2,4], target = 6
+输出:[1,2]
+

示例 3:

1
+2
+
输入:nums = [3,3], target = 6
+输出:[0,1]
+

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

(2)思路

根据提示:只存在一个有效答案。所以我们这里可以选择unordered_map

接下来我们明确两点:

  • map用来做什么
  • map中key和value分别表示什么

拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。

所以在map中的存储结构为:{key:数据元素, value:数组元素对应的下标}

image-20230220210132750

image-20230220211643116

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+
class Solution {
+public:
+    vector<int> twoSum(vector<int>& nums, int target) {
+        std::unordered_map <int,int> map;
+        for(int i = 0; i < nums.size(); i++) {
+            // 遍历当前元素,并在map中寻找是否有匹配的key
+            auto iter = map.find(target - nums[i]); 
+            if(iter != map.end()) {
+                return {iter->second, i};
+            }
+            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
+            map.insert(pair<int, int>(nums[i], i)); 
+        }
+        return {};
+    }
+};
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642.jpg" new file mode 100644 index 000000000..917a57e0e Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642_hu0ba98275d6445c79f820f07c37ff307c_127855_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642_hu0ba98275d6445c79f820f07c37ff307c_127855_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..4e585b26b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.3d2d3ae3736c2fd835559d676cd22642_hu0ba98275d6445c79f820f07c37ff307c_127855_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.jpg" new file mode 100644 index 000000000..917a57e0e Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..6a9e42520 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..6c28f9f1d Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..11403c712 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/index.html" new file mode 100644 index 000000000..c6aca28ca --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\223\210\345\270\214\350\241\2502\345\233\233\346\225\260\347\233\270\345\212\240ii-\350\265\216\351\207\221\344\277\241-\344\270\211\346\225\260\344\271\213\345\222\214-\345\233\233\346\225\260\344\271\213\345\222\214/index.html" @@ -0,0 +1,522 @@ +【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和 +
Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和

【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和

算法任务:leetcode454.四数相加II、leetcode383.赎金信、leetcode15.三数之和、leetcode18.四数之和

+
+

今日任务

  • 454.四数相加II
  • 383.赎金信
  • 15.三数之和
  • 18.四数之和

1.Leetcode454.四数相加II

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii

(1)题目

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

示例 1:

1
+2
+3
+4
+5
+6
+7
+
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
+输出:2
+解释:
+两个元组如下:
+
+1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
+2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
+

示例 2:

1
+2
+
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
+输出:1
+

提示:

  • n == nums1.length
  • n == nums2.length
  • n == nums3.length
  • n == nums4.length
  • 1 <= n <= 200
  • -228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228

(2)思路

分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。

解题步骤:

  • 首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。
  • 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。
  • 定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。
  • 在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
  • 最后再返回统计值count就可以了。

(3)代码演示

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
class Solution {
+public:
+    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
+        unordered_map<int, int> umap; // key:a+b的数值,value:a+b数值出现的次数
+        for(int a : nums1){
+            for(int b : nums2){
+                umap[a + b]++; // 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中
+            }
+        }
+        int count = 0; // 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数
+        // 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
+        for(int c : nums3){
+            for(int d : nums4){
+                if(umap.find(0 - (c + d)) != umap.end()){
+                    count += umap[0 - (c + d)];// 此处 umap[key]可以直接访问满足key的value值
+                }
+            }
+        }
+        return count;
+    }
+};
+

2.Leetcode383.赎金信

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note

(1)题目

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

示例 1:

1
+2
+
输入:ransomNote = "a", magazine = "b"
+输出:false
+

示例 2:

1
+2
+
输入:ransomNote = "aa", magazine = "ab"
+输出:false
+

示例 3:

1
+2
+
输入:ransomNote = "aa", magazine = "aab"
+输出:true
+

提示:

  • 1 <= ransomNote.length, magazine.length <= 105
  • ransomNote 和 magazine 由小写英文字母组成

(2)思路

首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。

对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的,所以数组和map果断选择map。

暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。

使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一

(3)暴力解法

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
// 时间复杂度: O(n^2)
+// 空间复杂度:O(1)
+class Solution {
+public:
+    bool canConstruct(string ransomNote, string magazine) {
+        for (int i = 0; i < magazine.length(); i++) {
+            for (int j = 0; j < ransomNote.length(); j++) {
+                // 在ransomNote中找到和magazine相同的字符
+                if (magazine[i] == ransomNote[j]) {
+                    ransomNote.erase(ransomNote.begin() + j); // ransomNote删除这个字符
+                    break;
+                }
+            }
+        }
+        // 如果ransomNote为空,则说明magazine的字符可以组成ransomNote
+        if (ransomNote.length() == 0) {
+            return true;
+        }
+        return false;
+    }
+};
+

(4)哈希解法

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
// 时间复杂度: O(n)
+// 空间复杂度:O(1)
+class Solution {
+public:
+    bool canConstruct(string ransomNote, string magazine) {
+        int record[26] = {0};
+        //add
+        if (ransomNote.size() > magazine.size()) {
+            return false;
+        }
+        for (int i = 0; i < magazine.length(); i++) {
+            // 通过recode数据记录 magazine里各个字符出现次数
+            record[magazine[i]-'a'] ++;
+        }
+        for (int j = 0; j < ransomNote.length(); j++) {
+            // 遍历ransomNote,在record里对应的字符个数做--操作
+            record[ransomNote[j]-'a']--;
+            // 如果小于零说明ransomNote里出现的字符,magazine没有
+            if(record[ransomNote[j]-'a'] < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+};
+

3.Leetcode15.三数之和

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum

(1)题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

1
+2
+3
+4
+5
+6
+7
+8
+
输入:nums = [-1,0,1,2,-1,-4]
+输出:[[-1,-1,2],[-1,0,1]]
+解释:
+nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 
+nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 
+nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 
+不同的三元组是 [-1,0,1]  [-1,-1,2] 
+注意,输出的顺序和三元组的顺序并不重要。
+

示例 2:

1
+2
+3
+
输入:nums = [0,1,1]
+输出:[]
+解释:唯一可能的三元组和不为 0 
+

示例 3:

1
+2
+3
+
输入:nums = [0,0,0]
+输出:[[0,0,0]]
+解释:唯一可能的三元组和为 0 
+

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

(2)思路

这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了答案中不可包含重复的三元组。所以解题思路不能一概而论,同样可以使用哈希解法,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。

那么另外一种解题思路就是使用双指针法。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:

image-20230221204834894

我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:

  • nums[i] + nums[left] + nums[right] > 0 :此时说明三数之和大了,需要我们将right下标向左移动
  • nums[i] + nums[left] + nums[right] = 0 :返回结果
  • nums[i] + nums[left] + nums[right] < 0 :说明此时三数之和小了,需要我们将left下标向右移动

此外,我们还需要解决去重的问题:

<1>对a去重:

按照一贯的理解我们可能是下面这种做法:

1
+2
+3
+
            if (i > 0 && nums[i] == nums[i + 1]) { //三元组元素a去重
+                continue;
+            }
+

但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:返回不能有重复的三元组,但是三元组内的元素是可以重复的,如果按照上面的写法,那么我们很可能漏掉一组解。

所以应该是下面这段代码这样:

1
+2
+3
+
            if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重
+                continue;
+            }
+

image-20230221205206723

<2>b与c的去重:

当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。

image-20230221211026547

1
+2
+3
+
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
+                    while (right > left && nums[right] == nums[right - 1]) right--;
+                    while (right > left && nums[left] == nums[left + 1]) left++;
+

image-20230221211127566

1
+2
+3
+
                    // 找到答案时,双指针同时收缩
+                    right--;
+                    left++;
+

image-20230221211223973

(3)哈希解法*

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
class Solution {
+public:
+    vector<vector<int>> threeSum(vector<int>& nums) {
+        vector<vector<int>> result;
+        sort(nums.begin(), nums.end());
+        // 找出a + b + c = 0
+        // a = nums[i], b = nums[j], c = -(a + b)
+        for (int i = 0; i < nums.size(); i++) {
+            // 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
+            if (nums[i] > 0) {
+                break;
+            }
+            if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重
+                continue;
+            }
+            unordered_set<int> set;
+            for (int j = i + 1; j < nums.size(); j++) {
+                if (j > i + 2
+                        && nums[j] == nums[j-1]
+                        && nums[j-1] == nums[j-2]) { // 三元组元素b去重
+                    continue;
+                }
+                int c = 0 - (nums[i] + nums[j]);
+                if (set.find(c) != set.end()) {
+                    result.push_back({nums[i], nums[j], c});
+                    set.erase(c);// 三元组元素c去重
+                } else {
+                    set.insert(nums[j]);
+                }
+            }
+        }
+        return result;
+    }
+};
+

(4)双指针法

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
class Solution {
+public:
+    vector<vector<int>> threeSum(vector<int>& nums) {
+        vector<vector<int>> result;
+        sort(nums.begin(), nums.end());
+        // 找出a + b + c = 0
+        // a = nums[i], b = nums[left], c = nums[right]
+        for (int i = 0; i < nums.size(); i++) {
+            // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
+            if (nums[i] > 0) {
+                return result;
+            }
+            // 错误去重a方法,将会漏掉-1,-1,2 这种情况
+            /*
+            if (nums[i] == nums[i + 1]) {
+                continue;
+            }
+            */
+            // 正确去重a方法
+            if (i > 0 && nums[i] == nums[i - 1]) {
+                continue;
+            }
+            int left = i + 1;
+            int right = nums.size() - 1;
+            while (right > left) {
+                // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
+                /*
+                while (right > left && nums[right] == nums[right - 1]) right--;
+                while (right > left && nums[left] == nums[left + 1]) left++;
+                */
+                if (nums[i] + nums[left] + nums[right] > 0) right--;
+                else if (nums[i] + nums[left] + nums[right] < 0) left++;
+                else {
+                    result.push_back(vector<int>{nums[i], nums[left], nums[right]});
+                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
+                    while (right > left && nums[right] == nums[right - 1]) right--;
+                    while (right > left && nums[left] == nums[left + 1]) left++;
+
+                    // 找到答案时,双指针同时收缩
+                    right--;
+                    left++;
+                }
+            }
+
+        }
+        return result;
+    }
+};
+

4.Leetcode18.四数之和

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum

(1)题目

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n

  • a、b、c 和 d 互不相同

  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

1
+2
+
输入:nums = [1,0,-1,0,-2,2], target = 0
+输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
+

示例 2:

1
+2
+
输入:nums = [2,2,2,2,2], target = 8
+输出:[[2,2,2,2]]
+

提示:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109

(2)思路

这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。

但是有些许细节需要我们认真对待:

  • 在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。
  • 在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是nums[k] + nums[i] + nums[left] + nums[right] == target的所有可解集合,所以我们的解决方法是两层for循环nums[k] + nums[i]为确定值,双指针法依然是left和right作为下标。
  • 三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。

image-20230221214611511

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
class Solution {
+public:
+    vector<vector<int>> fourSum(vector<int>& nums, int target) {
+        vector<vector<int>> result;
+        sort(nums.begin(), nums.end());
+        for (int k = 0; k < nums.size(); k++) {
+            // 剪枝处理
+            if (nums[k] > target && nums[k] >= 0) {
+            	break; // 这里使用break,统一通过最后的return返回
+            }
+            // 对nums[k]去重
+            if (k > 0 && nums[k] == nums[k - 1]) {
+                continue;
+            }
+            for (int i = k + 1; i < nums.size(); i++) {
+                // 2级剪枝处理
+                if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
+                    break;
+                }
+
+                // 对nums[i]去重
+                if (i > k + 1 && nums[i] == nums[i - 1]) {
+                    continue;
+                }
+                int left = i + 1;
+                int right = nums.size() - 1;
+                while (right > left) {
+                    // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
+                    if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {
+                        right--;
+                    // nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
+                    } else if ((long) nums[k] + nums[i] + nums[left] + nums[right]  < target) {
+                        left++;
+                    } else {
+                        result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
+                        // 对nums[left]和nums[right]去重
+                        while (right > left && nums[right] == nums[right - 1]) right--;
+                        while (right > left && nums[left] == nums[left + 1]) left++;
+
+                        // 找到答案时,双指针同时收缩
+                        right--;
+                        left++;
+                    }
+                }
+
+            }
+        }
+        return result;
+    }
+};
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4.jpg" new file mode 100644 index 000000000..7a7043b5b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4_hubd45134fe7e482c9d30a491cd239645b_134507_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4_hubd45134fe7e482c9d30a491cd239645b_134507_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c0463663b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.ae7bdbb57cc33ec82935a4a2210e49d4_hubd45134fe7e482c9d30a491cd239645b_134507_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.jpg" new file mode 100644 index 000000000..7a7043b5b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9e75c0787 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c06225353 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..209b6a81d Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/cover_hubd45134fe7e482c9d30a491cd239645b_134507_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/index.html" new file mode 100644 index 000000000..47664ce9d --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2621\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262i-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262ii-\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215-\345\211\221\346\214\207offer\346\233\277\346\215\242\347\251\272\346\240\274\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262/index.html" @@ -0,0 +1,324 @@ +【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串) +
Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)

【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)

算法任务:反转字符串I、反转字符串II、反转字符串里的单词、剑指offer(替换空格、左旋转字符串)

+
+

今日任务

  • 344.反转字符串
  • 541.反转字符串II
  • 剑指Offer 05.替换空格
  • 151.反转字符串里的单词
  • 剑指Offer58-II.左旋转字符串

1.Leetcode344.反转字符串

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string

(1)题目

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

1
+2
+
输入:s = ["h","e","l","l","o"]
+输出:["o","l","l","e","h"]
+

示例 2:

1
+2
+
输入:s = ["H","a","n","n","a","h"]
+输出:["h","a","n","n","a","H"]
+

提示:

  • 1 <= s.length <= 105
  • s[i] 都是 ASCII 码表中的可打印字符

(2)思路

看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。

那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。

image-20230222111753143

对应的部分C++代码:

1
+2
+3
+4
+5
+
void reverseString(vector<char>& s){
+	for(int i = 0, j = s.size() - 1; i < s.size() / 2; i++,j--){
+		swap(s[i], s[j]);
+    }
+}
+

(3)代码演示

1
+2
+3
+4
+5
+6
+7
+8
+
class Solution {
+public:
+    void reverseString(vector<char>& s) {
+        for (int i = 0, j = s.size() - 1; i < s.size()/2; i++, j--) {
+            swap(s[i],s[j]);
+        }
+    }
+};
+

2.Leetcode541.反转字符串II

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii

(1)题目

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:

1
+2
+
输入:s = "abcdefg", k = 2
+输出:"bacdfeg"
+

示例 2:

1
+2
+
输入:s = "abcd", k = 2
+输出:"bacd"
+

提示:

  • 1 <= s.length <= 104
  • s 仅由小写英文组成
  • 1 <= k <= 104

(2)思路

我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

该题主要需要解决两个问题:

  • 每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符
  • 对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符

具体详细的解题步骤请看下图及代码:

image-20230222121250753

(3)代码演示

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
class Solution {
+public:
+    // 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数
+    void reverse(string& s, int start, int end) {
+        for (int i = start, j = end; i < j; i++, j--) {
+            swap(s[i], s[j]);
+        }
+    }
+    string reverseStr(string s, int k) {
+        for (int i = 0; i < s.size(); i += (2 * k)) {
+            // 1. 每隔 2k 个字符的前 k 个字符进行反转
+            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
+            if (i + k <= s.size()) {
+                reverse(s, i, i + k - 1);
+                continue;
+            }
+            // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
+            reverse(s, i, s.size() - 1);
+        }
+        return s;
+    }
+};
+

reverse()

  • reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include
  • reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值

3.剑指Offer 05.替换空格

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof

(1)题目

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:

1
+2
+
输入:s = "We are happy."
+输出:"We%20are%20happy."
+

限制:

  • 0 <= s 的长度 <= 10000

(2)思路

对这道题的求解,主要分三个步骤:

  • 首先扩充数组到每个空格替换成"%20"之后的大小
  • 然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)
  • i指向新长度的末尾,j指向旧长度的末尾

替换空格

而这里也有一个小技巧:遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。

这样做的好处:

  • 不用申请新数组
  • 从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。

(3)代码演示

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
class Solution {
+public:
+    string replaceSpace(string s) {
+        int count = 0; // 统计空格的个数
+        int sOldSize = s.size();
+        for (int i = 0; i < s.size(); i++) {
+            if (s[i] == ' ') {
+                count++;
+            }
+        }
+        // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
+        s.resize(s.size() + count * 2); // 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了
+        int sNewSize = s.size();
+        // 从后先前将空格替换为"%20"
+        for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
+            if (s[j] != ' ') {
+                s[i] = s[j];
+            } else {
+                s[i] = '0';
+                s[i - 1] = '2';
+                s[i - 2] = '%';
+                i -= 2;
+            }
+        }
+        return s;
+    }
+};
+

resize()

  • 既分配了空间,也创建了对象。
  • 这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。

4.Leetcode151.反转字符串里的单词

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string

(1)题目

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

1
+2
+
输入:s = "the sky is blue"
+输出:"blue is sky the"
+

示例 2:

1
+2
+3
+
输入:s = "  hello world  "
+输出:"world hello"
+解释:反转后的字符串中不能存在前导空格和尾随空格。
+

示例 3:

1
+2
+3
+
输入:s = "a good   example"
+输出:"example good a"
+解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
+

提示:

  • 1 <= s.length <= 104
  • s 包含英文大小写字母、数字和空格 ’ '
  • s 中 至少存在一个 单词

进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。

(2)思路

对于这样一道题,我们不使用辅助空间,空间复杂度要求为O(1)

所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决

  • 首先移除掉多余的空格
  • 将整个字符串反转
  • 再将每个单词反转

演示如下:

image-20230222154346894

前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看移除多余空格:我们的做法是通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
+    int slow = 0;  
+    for (int i = 0; i < s.size(); ++i) { //
+        if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
+            if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
+            while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
+                s[slow++] = s[i++];
+            }
+        }
+    }
+    s.resize(slow); //slow的大小即为去除多余空格后的大小。
+}
+

此外就是字符串反转的问题,其代码实现逻辑如下:

1
+2
+3
+4
+5
+6
+
// 反转字符串s中左闭右闭的区间[start, end]
+void reverse(string& s, int start, int end) {
+    for (int i = start, j = end; i < j; i++, j--) {
+        swap(s[i], s[j]);
+    }
+}
+

(3)代码演示

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
class Solution {
+public:
+    void reverse(string& s, int start, int end){ //翻转,区间写法:左闭右闭 []
+        for (int i = start, j = end; i < j; i++, j--) {
+            swap(s[i], s[j]);
+        }
+    }
+
+    void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
+        int slow = 0;   //整体思想参考https://programmercarl.com/0027.移除元素.html
+        for (int i = 0; i < s.size(); ++i) { //
+            if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
+                if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
+                while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
+                    s[slow++] = s[i++];
+                }
+            }
+        }
+        s.resize(slow); //slow的大小即为去除多余空格后的大小。
+    }
+
+    string reverseWords(string s) {
+        removeExtraSpaces(s); //去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。
+        reverse(s, 0, s.size() - 1);// 反转字符串
+        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
+        for (int i = 0; i <= s.size(); ++i) {
+            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
+                reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
+                start = i + 1; //更新下一个单词的开始下标start
+            }
+        }
+        return s;
+    }
+};
+

5.剑指Offer58-II.左旋转字符串

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof

(1)题目

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

1
+2
+
输入: s = "abcdefg", k = 2
+输出: "cdefgab"
+

示例 2:

1
+2
+
输入: s = "lrloseumgh", k = 6
+输出: "umghlrlose"
+

限制:

  • 1 <= k < s.length <= 10000

(2)思路

在本题目中,carl老师继续升级难度:要求不能申请额外空间,只能在本串上操作

但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:

  • 反转区间为前n的子串
  • 反转区间为n到末尾的子串
  • 反转整个字符串

image-20230222162131830

这样一来,整体的代码逻辑就特别简单啦!

(3)代码演示

1
+2
+3
+4
+5
+6
+7
+8
+9
+
class Solution {
+public:
+    string reverseLeftWords(string s, int n) {
+        reverse(s.begin(), s.begin() + n);
+        reverse(s.begin() + n, s.end());
+        reverse(s.begin(), s.end());
+        return s;
+    }
+};
+

没想到最后一个代码的实现这么简单哈哈哈,在经历Leetcode151.反转字符串里的单词这道题的洗礼后是不是有种小巫见大巫的想法。

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc.jpg" new file mode 100644 index 000000000..b381066eb Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc_hu0ba98275d6445c79f820f07c37ff307c_142192_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc_hu0ba98275d6445c79f820f07c37ff307c_142192_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..995a38c5b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.ae324f4ec50423f93b4678fbd1e144dc_hu0ba98275d6445c79f820f07c37ff307c_142192_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.jpg" new file mode 100644 index 000000000..b381066eb Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..bc391768f Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..821496058 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..d438b3271 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/index.html" new file mode 100644 index 000000000..d482a21a8 --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\345\255\227\347\254\246\344\270\2622kmp-\345\256\236\347\216\260-strstr-\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262/index.html" @@ -0,0 +1,382 @@ +【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串 +
Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串

【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串

算法任务:KMP算法详解、Leetcode28实现 strStr()、Leetcode459.重复的子字符串

+
+

今日任务

  • KMP算法详解
  • 28.实现 strStr()
  • 459.重复的子字符串
  • 字符串总结
  • 双指针回顾

1.KMP算法详解

由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。

(1)什么是KMP算法

说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。

因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。

(2)KMP的作用

KMP主要体现在字符串匹配上。

KMP算法的主要思想是当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。

因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。

(3)什么是前缀表

前缀表有什么作用呢?

前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。

其中我们会了解到next数组,next数组其实就是一个前缀表(prefix table)

为了更加清楚地了解前缀表的来历,我们来举一个例子:

在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。

如下面动画所示(来源:代码随想录):

KMP精讲1

我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。

那么前缀表时如何记录的呢?

首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。

所以前缀表的定义是:记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀

(4)什么是最长公共前后缀

前文中字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串

后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串

image-20230226205706410

那么我们回到最长公共前后缀,更加准确的理解应该是“最长相等前后缀”,因为前缀表的要求就是相同前后缀

而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。

所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。

(5)如何计算前缀表

我们先来看几个例子:

image-20230225205304564

解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.

注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。

image-20230225205831598

解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.

image-20230225210252121

解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.

以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.

最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:

image-20230225213153188

可以看出模式串与前缀表对应位置的数字表示的就是:下标i之前(包括i)的字符串中,有多大长度的相同前后缀.

我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:

KMP精讲2

当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。

之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。

所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。

(5)前缀表与next数组

很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?

前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。

(6)使用next数组匹配

以下我们以前缀表统一减一之后的next数组来做演示。

注意此时的前缀表已经实现同一减一了,匹配动画如下:

KMP精讲4

(7)时间复杂度分析

其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)

而暴力解法的时间复杂度明显是O(n * m),所以可知KMP在字符串匹配中极大地提高了搜索的效率

2.Leetcode28.实现 strStr()

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string

(1)题目

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

示例 1:

1
+2
+3
+4
+
输入:haystack = "sadbutsad", needle = "sad"
+输出:0
+解释:"sad" 在下标 0  6 处匹配。
+第一个匹配项的下标是 0 ,所以返回 0 
+

示例 2:

1
+2
+3
+
输入:haystack = "leetcode", needle = "leeto"
+输出:-1
+解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 
+

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystack 和 needle 仅由小写英文字符组成

(2)思路

前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。

在本题目中,haystack(文本串),needle(模式串)。

解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。

<1>构造next数组

我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:

1
+
void getNext(int* next, const string& s)
+

**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:

  • 1.初始化
  • 2.处理前后缀不相同的情况
  • 3.处理前后缀相同的情况

下面我们来详细讲解:

1.初始化

定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。

然后对next数组进行初始化赋值:

1
+2
+
int j = -1;
+next[0] = j;
+

这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)

next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)

所以初始化为next[0] = j;

2.处理前后缀不相同的情况

因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。

所以遍历模式串s的循环下标i要从1开始,代码如下:

1
+
for(int i = 1; i < s.size(); i++){}
+

如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。

这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。

s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。

所以,处理前后缀不相同的情况的代码如下所示:

1
+2
+3
+
while(j >= 0 && s[i] != s[j + 1]){ //前后缀不相同的情况
+    j = next[j];	// 向前回退
+}
+

注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。

3.处理前后缀相同的情况

如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:

1
+2
+3
+4
+
if(s[i] == s[j + 1]){ // 找到相同的前后缀
+    j++;
+}
+next[i] = j;
+

最后整体构建next数组的函数代码如下所示:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+
void getNext(int* next, const string& s){
+    int j = -1;
+    next[0] = j;
+    for(int i = 1; i < s.size(); i++){	// 注意i从1开始
+        while(j >= 0 && s[i] != s[j + 1]){	// 前后缀不相同的时候
+            j = next[j];	// 向前回退
+        }
+        if(s[i] == s[j + 1]){ 	// 找到相同的前后缀
+            j++;
+        }
+        next[i] = j;	// 将j(前缀的长度)赋值给next[i]
+    }
+}
+

代码构造next数组的逻辑流程动画如下(来源:代码随想录):

KMP精讲3

<2>使用next数组进行匹配

目标:在文本串中找是否出现过模式串t。

首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。

此时j初始值依然为-1,因为next数组中记录的起始位置为-1.

i从0开始,遍历文本串,代码如下:

1
+
for(int i = 0; i < s.size(); i++)
+

接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。

如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:

1
+2
+3
+
while(j >= 0 && s[i] != t[j + 1]){
+    j = next[j];
+}
+

如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:

1
+2
+3
+
if(s[i] == t[j + 1]){
+    j++;	// i的增加在for循环中定义
+}
+

那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。

模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:

1
+2
+3
+
if(j == (t.size() - 1)){
+	return (i - t.size() + 1);
+}
+

因此使用next数组,用模式串匹配文本串的整体代码如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
int j = -1;	// 因为next数组里记录的起始位置为-1
+for(int i = 0; i < s.size(); i++){	// 注意i从0开始
+    while(j >= 0 && s[i] != t[j + 1]){	// 不匹配
+    	j = next[j]; 	// j寻找之前匹配的位置
+    }
+    if(s[i] == t[j + 1]){	// 匹配,j和i同时向后移动
+    	j++;	// i的增加在for循环中
+    }
+    if(j == (t.size() - 1)){	// 文本串s里出现了模式串t
+    	return (i - t.size() + 1);
+    }
+}
+

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
// 前缀表统一减一
+
+class Solution {
+public:
+    void getNext(int* next, const string& s) {
+        int j = -1;
+        next[0] = j;
+        for(int i = 1; i < s.size(); i++) { // 注意i从1开始
+            while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
+                j = next[j]; // 向前回退
+            }
+            if (s[i] == s[j + 1]) { // 找到相同的前后缀
+                j++;
+            }
+            next[i] = j; // 将j(前缀的长度)赋给next[i]
+        }
+    }
+    int strStr(string haystack, string needle) {
+        if (needle.size() == 0) {
+            return 0;
+        }
+        int next[needle.size()];
+        getNext(next, needle);
+        int j = -1; // // 因为next数组里记录的起始位置为-1
+        for (int i = 0; i < haystack.size(); i++) { // 注意i就从0开始
+            while(j >= 0 && haystack[i] != needle[j + 1]) { // 不匹配
+                j = next[j]; // j 寻找之前匹配的位置
+            }
+            if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动
+                j++; // i的增加在for循环里
+            }
+            if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串t
+                return (i - needle.size() + 1);
+            }
+        }
+        return -1;
+    }
+};
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
// 前缀表(不减一)
+
+class Solution {
+public:
+    void getNext(int* next, const string& s) {
+        int j = 0;
+        next[0] = 0;
+        for(int i = 1; i < s.size(); i++) {
+            while (j > 0 && s[i] != s[j]) {
+                j = next[j - 1];
+            }
+            if (s[i] == s[j]) {
+                j++;
+            }
+            next[i] = j;
+        }
+    }
+    int strStr(string haystack, string needle) {
+        if (needle.size() == 0) {
+            return 0;
+        }
+        int next[needle.size()];
+        getNext(next, needle);
+        int j = 0;
+        for (int i = 0; i < haystack.size(); i++) {
+            while(j > 0 && haystack[i] != needle[j]) {
+                j = next[j - 1];
+            }
+            if (haystack[i] == needle[j]) {
+                j++;
+            }
+            if (j == needle.size() ) {
+                return (i - needle.size() + 1);
+            }
+        }
+        return -1;
+    }
+};
+

3.Leetcode459.重复的子字符串

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern

(1)题目

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

1
+2
+3
+
输入: s = "abab"
+输出: true
+解释: 可由子串 "ab" 重复两次构成。
+

示例 2:

1
+2
+
输入: s = "aba"
+输出: false
+

示例 3:

1
+2
+3
+
输入: s = "abcabcabcabc"
+输出: true
+解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)
+

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

(2)思路

对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。

首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。

这里我们主要对移动匹配和KMP两种方法进行讲解。

<1>移动匹配

首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:

image-20230227090301956

那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。

image-20230227090746221

所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。

这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行掐头去尾(刨除s+s的首字符和尾字符),代码如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
class Solution{
+public:
+    bool repeatedSubstringPatterns(string s){
+        string t = s + s;
+        t.erase(t.begin());
+        t.erase(t.end() - 1);	// 掐头去尾
+        if(t.find(s) != std::string::npos) return true;
+        return false;
+    }
+};
+

虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。

<2>KMP

想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.

代码如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+
class Solution {
+public:
+    void getNext(int* next, const string& s){
+        next[0] = 0;
+        int j = 0;
+        for(int i = 1;i < s.size(); i++){
+            while(j > 0 && s[i] != s[j]){
+                j = next[j - 1];
+            }
+            if(s[i] == s[j]){
+                j++;
+            }
+            next[i] = j;
+        }
+    }
+    bool repeatedSubstringPattern(string s) {
+        if(s.size() == 0){
+            return false;
+        }
+        int next[s.size()];
+        getNext(next, s);
+        int len = s.size();
+        if(next[len - 1] != 0 && len % (len - (next[len - 1])) == 0){
+            return true;
+        }
+        return false;
+    }
+};
+

4.字符串总结

对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8.jpg" new file mode 100644 index 000000000..6de2922f4 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..037149e85 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.8b562c51143f9b8cbd260217745f9ea8_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.jpg" new file mode 100644 index 000000000..6de2922f4 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..97c2cbd49 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..523e92b80 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a94fb5aec Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/index.html" new file mode 100644 index 000000000..ed2b0fe27 --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2041\344\272\214\345\210\206\346\237\245\346\211\276-\347\247\273\351\231\244\345\205\203\347\264\240/index.html" @@ -0,0 +1,341 @@ +【数据结构与算法】数组1:二分查找 & 移除元素 +
Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素

【数据结构与算法】数组1:二分查找 & 移除元素

算法任务:数组理论基础、leetcode704.二分查找、leetcode27.移除元素

+
+

今日任务

  • 数组理论基础

  • 704.二分查找

  • 27.移除元素

1.数组理论基础

(1)数组是存放在连续内存空间上的相同类型数据的集合。

注意:

  • 数组下标都是从0开始的
  • 数组内存空间的地址是连续的

(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:

image-20230215112419117

(3)数组的元素是不能删除的,只能使用覆盖的方式。

(4)C++中二维数组在地址空间上是连续的。

通过编写一个程序来验证:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
#include <iostream>
+using namespace std;
+
+void test_arr(){
+        int array[2][3] =
+        {
+                {0,1,2},
+                {3,4,5}
+        };
+
+        cout << &array[0][0] << " "<< &array[0][1] <<" "<< &array[0][2] <<endl;
+        cout << &array[1][0] << " "<< &array[1][1] <<" "<< &array[1][2] <<endl;
+}
+
+int main()
+{
+        test_arr();
+}
+

image-20230215114525706

在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节

2.Leetcode704:二分查找

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search

(1)题目

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

1
+2
+3
+
输入: nums = [-1,0,3,5,9,12], target = 9
+输出: 4
+解释: 9 出现在 nums 中并且下标为 4
+

示例 2:

1
+2
+3
+
输入: nums = [-1,0,3,5,9,12], target = 2
+输出: -1
+解释: 2 不存在 nums 中因此返回 -1
+

提示:

  • 你可以假设 nums 中的所有元素是不重复的。
  • n 将在 [1, 10000]之间。
  • nums 的每个元素都将在 [-9999, 9999]之间。

(2)思路

首先确定关键词:

  • 数组为有序数组
  • 数组无重复元素

根据题目和提示,我们联想到二分法。

(3)二分法

简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。

关于二分法的写法,区间的定义一般分为两种:

  • 左闭右闭 [left, right]
  • 左闭右开 [left, right)

根据二分法的两种写法,我们分别求解:

<1>第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]

区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:

  • while(left <= right) 要使用 <=,因为left == right 是有意义的,所以使用 <=
  • if (nums[middle] > target) right要赋值为middle-1
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
// 下面是一段伪代码形式来讲解
+
+首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:
+Left | Right | Middle | target
+
+很明显 Left = 数组下标0	Right为 NumSize(array)-1	Middle = (Left + Right) / 2
+所以编写如下函数:
+    
+//	因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑
+while(left <= right)		
+{
+    // 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1
+    if(Num(middle) > Num(target))
+        Num(right) = Num(middle) - 1;
+    // 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1
+    else if(Num(middle) < Num(target))
+        Num(left) = Num(middle) + 1;
+    // 那么第三种情况也就是middle直接等于target,返回即可
+    else
+        return middle;
+}
+return -1;
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
// 版本一
+class Solution {
+public:
+    int search(vector<int>& nums, int target) {
+        int left = 0;
+        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
+        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
+            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
+            if (nums[middle] > target) {
+                right = middle - 1; // target 在左区间,所以[left, middle - 1]
+            } else if (nums[middle] < target) {
+                left = middle + 1; // target 在右区间,所以[middle + 1, right]
+            } else { // nums[middle] == target
+                return middle; // 数组中找到目标值,直接返回下标
+            }
+        }
+        // 未找到目标值
+        return -1;
+    }
+};
+

<2>第二种写法,我们定义target是在一个左闭右开,也就是[left, right)

根据左闭右开的方式,那么处理方式有如下两点:

  • while(left < right),这里使用 <,因为left == right在区间 [left, right)是没有意义的
  • if(Num(middle) > target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
// 下面是一段伪代码形式来讲解
+
+// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值:
+
+Left | Right | Middle | target
+
+上面的定义不变,但是函数主体需要有一些改动了
+    
+//	注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array),
+while(left < right)		
+{
+    // 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle)
+    if(Num(middle) > Num(target))
+        Num(right) = Num(middle);
+    // 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1
+    else if(Num(middle) < Num(target))
+        Num(left) = Num(middle) + 1;
+    // 那么第三种情况也就是middle直接等于target,返回即可
+    else
+        return middle;
+}
+return -1;
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
// 版本二
+class Solution {
+public:
+    int search(vector<int>& nums, int target) {
+        int left = 0;
+        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
+        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
+            int middle = left + ((right - left) >> 1);
+            if (nums[middle] > target) {
+                right = middle; // target 在左区间,在[left, middle)中
+            } else if (nums[middle] < target) {
+                left = middle + 1; // target 在右区间,在[middle + 1, right)中
+            } else { // nums[middle] == target
+                return middle; // 数组中找到目标值,直接返回下标
+            }
+        }
+        // 未找到目标值
+        return -1;
+    }
+};
+

上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:

解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2

image-20230215143931951

解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。

解析二:int middle = left + ((right - left) >> 1);

image-20230215144334277

解答:>>是位运算的符号,>>1代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11»1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。

此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为移位指令占2个机器周期,而乘除法指令占4个机器周期。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。

3.Leetcode27:移除元素

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element

(1)题目

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

1
+2
+3
+4
+5
+6
+7
+8
+
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
+int len = removeElement(nums, val);
+
+// 在函数里修改输入数组对于调用者是可见的。
+// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
+for (int i = 0; i < len; i++) {
+    print(nums[i]);
+}
+

示例 1:

1
+2
+3
+
输入:nums = [3,2,2,3], val = 3
+输出:2, nums = [2,2]
+解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3]  nums = [2,2,0,0],也会被视作正确答案。
+

示例 2:

1
+2
+3
+
输入:nums = [0,1,2,2,3,0,4,2], val = 2
+输出:5, nums = [0,1,4,0,3]
+解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
+

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100

(2)思路

首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

对此我们使用暴力解法

(3)暴力解法

解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+
class Solution{
+public:
+    int removeElement(vector<int>& nums, int val){
+		int size = nums.size();
+        for(int i = 0; i < size; i++){
+            if(nums[i] == val){		// 发现需要移除的元素,就将数组集体向前移动一位
+				for(int j = i + 1; j < size; j++){		
+					nums[j - 1] = nums[j];
+                }
+                i--			  // 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位
+                size--;			   // 相对应的数组大小-1
+            }
+        }
+        
+        return size;
+    }
+};
+

说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。

(4)双指针法

除了暴力解法,双指针法也同样适用于此场景。

通过定义两个指针,一个slow指针和一个fast指针, 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

  • fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组
  • slow指针:指向更新 新数组下标的位置
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+
// 时间复杂度:O(n)
+// 空间复杂度:O(1)
+class Solution {
+public:
+    int removeElement(vector<int>& nums, int val) {
+        int slowIndex = 0;
+        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
+            if (val != nums[fastIndex]) {		// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位
+                nums[slowIndex++] = nums[fastIndex];
+            }
+            // 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配
+        }
+        return slowIndex;
+    }
+};
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f.jpg" new file mode 100644 index 000000000..3ffaf4477 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f_hu0ba98275d6445c79f820f07c37ff307c_129507_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f_hu0ba98275d6445c79f820f07c37ff307c_129507_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f6a376aba Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.b2fd05d322aec9d66c36698fa221859f_hu0ba98275d6445c79f820f07c37ff307c_129507_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.jpg" new file mode 100644 index 000000000..3ffaf4477 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f1be68a22 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..6605739ff Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..097b21779 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/index.html" new file mode 100644 index 000000000..c73004e10 --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\225\260\347\273\2042\345\217\214\346\214\207\351\222\210\346\263\225-\344\272\214\345\210\206\346\263\225\350\236\272\346\227\213\347\237\251\351\230\265/index.html" @@ -0,0 +1,303 @@ +【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵) +
Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)

【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)

算法任务:数组理论基础、leetcode704.二分查找、leetcode27.移除元素

+
+

今日任务

  • 977.有序数列的平方

  • 209.长度最小的子数组

  • 59.螺旋矩阵II

1.Leetcode977:有序数列的平方

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array

(1)题目

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

1
+2
+3
+4
+
输入:nums = [-4,-1,0,3,10]
+输出:[0,1,9,16,100]
+解释:平方后,数组变为 [16,1,0,9,100]
+排序后,数组变为 [0,1,9,16,100]
+

示例 2:

1
+2
+
输入:nums = [-7,-3,2,3,11]
+输出:[4,9,9,49,121]
+

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 已按 非递减顺序 排序

进阶:

请你设计时间复杂度为 O(n) 的算法解决本问题

(2)思路

最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。

(3)暴力排序

有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
class Solution {
+public:
+    vector<int> sortedSquares(vector<int>& nums) {
+        for(int i = 0; i < nums.size(); i++){
+            // nums[i] = pow(abs(nums[i]),2);
+            nums[i] *= nums[i];
+        }
+        sort(nums.begin(),nums.end());
+        return nums;
+    }
+};
+

说明:

  • pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)—>2^2=4;
  • abs(n):对n求绝对值

解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)

**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **

(4)双指针法

根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。

  • 定义一个新数组result,和数组A一样的大小,让K指向result数组终止位置
  • 如果A[i] *A[i] < A[j] * A[j],那么result[k–] = A[j] * A[j];
  • 如果A[i] *A[i] > A[j] * A[j],那么result[k–] = A[i] * A[i];
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
class Solution {
+public:
+    vector<int> sortedSquares(vector<int>& nums) {
+        vector<int> result(nums.size(),0);
+        int k = nums.size() - 1;
+        for(int i = 0,j = nums.size() - 1; i <= j; ){
+            if(nums[i] * nums[i] < nums[j] * nums[j]){
+                result[k--] = nums[j] * nums[j];
+                j--;
+            }
+            else{
+                result[k--] = nums[i] * nums[i];
+                i++;
+            }
+        }
+        return result;
+    }
+};
+

通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!

2.Leetcode209:长度最小的子数组

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum

(1)题目

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

1
+2
+3
+
输入:target = 7, nums = [2,3,1,2,4,3]
+输出:2
+解释:子数组 [4,3] 是该条件下的长度最小的子数组。
+

示例 2:

1
+2
+
输入:target = 4, nums = [1,4,4]
+输出:1
+

示例 3:

1
+2
+
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
+输出:0
+

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

(2)思路

首先分析题意,最明显的就是要求是连续子数组,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。

(3)暴力排序

对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
class Solution {
+public:
+    int minSubArrayLen(int target, vector<int>& nums) {
+        int result = INT32_MAX; // 最终的结果
+        int sum = 0; // 子序列的数值之和
+        int subLength = 0; // 子序列的长度
+        for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
+            sum = 0;
+            for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
+                sum += nums[j];
+                if (sum >= target) { // 一旦发现子序列和超过了s,更新result
+                    subLength = j - i + 1; // 取子序列的长度
+                    result = result < subLength ? result : subLength;
+                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
+                }
+            }
+        }
+        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
+        return result == INT32_MAX ? 0 : result;
+    }
+};
+
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。

(4)滑动窗口

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。

那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。

这里放上Carl大神的一张图,方便大家理解:

209.长度最小的子数组

那么最重要的两点来了:

  • 如何确定移动窗口的起始位置
  • 如何确定移动窗口的结束位置

解答如下:

  • 窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动
  • 窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
class Solution {
+public:
+    int minSubArrayLen(int target, vector<int>& nums) {
+        int result = INT32_MAX;
+        int sum = 0; // 滑动窗口数值之和
+        int i = 0; // 滑动窗口起始位置
+        int subLength = 0; // 滑动窗口的长度
+        for (int j = 0; j < nums.size(); j++) {
+            sum += nums[j];
+            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
+            while (sum >= target) {
+                subLength = (j - i + 1); // 取子序列的长度
+                result = result < subLength ? result : subLength;
+                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
+            }
+        }
+        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
+        return result == INT32_MAX ? 0 : result;
+    }
+};
+

在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)

3.Leetcode59:螺旋矩阵II

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii

(1)题目

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:

1
+2
+
输入:n = 3
+输出:[[1,2,3],[8,9,4],[7,6,5]]
+

示例 2:

1
+2
+
输入:n = 1
+输出:[[1]]
+

提示:

  • 1 <= n <= 20

(2)思路

在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持循环不变量原则

那么我们在模拟顺时针画矩阵时,遵循以下规则:

  • 填充上行从左往右
  • 填充右列从上往下
  • 填充下行从右往左
  • 填充左列从下往上

也就是如下图所示,好好理解一下!

img

回到题目,对于这种螺旋矩阵,我们首先要明确的坚持循环不变量原则,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。

这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的1、3、5、7,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。

(3)二分法求解

直接看代码部分:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
class Solution {
+public:
+    vector<vector<int>> generateMatrix(int n) {
+        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
+        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
+        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
+        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
+        int count = 1; // 用来给矩阵中每一个空格赋值
+        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
+        int i,j;
+        while (loop --) {
+            i = startx;
+            j = starty;
+
+            // 下面开始的四个for就是模拟转了一圈
+            // 模拟填充上行从左到右(左闭右开)
+            for (j = starty; j < n - offset; j++) {
+                res[startx][j] = count++;
+            }
+            // 模拟填充右列从上到下(左闭右开)
+            for (i = startx; i < n - offset; i++) {
+                res[i][j] = count++;
+            }
+            // 模拟填充下行从右到左(左闭右开)
+            for (; j > starty; j--) {
+                res[i][j] = count++;
+            }
+            // 模拟填充左列从下到上(左闭右开)
+            for (; i > startx; i--) {
+                res[i][j] = count++;
+            }
+
+            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
+            startx++;
+            starty++;
+
+            // offset 控制每一圈里每一条边遍历的长度
+            offset += 1;
+        }
+
+        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
+        if (n % 2) {
+            res[mid][mid] = count;
+        }
+        return res;
+    }
+};
+

4.总结

img

图片来源: 代码随想录知识星球成员:海螺人

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396.jpg" new file mode 100644 index 000000000..36e27914d Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396_hu0ba98275d6445c79f820f07c37ff307c_140407_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396_hu0ba98275d6445c79f820f07c37ff307c_140407_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d5b49bd5f Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.afad91c3c0e78a23a028bacffe4b6396_hu0ba98275d6445c79f820f07c37ff307c_140407_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.jpg" new file mode 100644 index 000000000..36e27914d Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..fabe7a13e Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a7011b01b Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a9e450324 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/index.html" new file mode 100644 index 000000000..916299f5d --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2501\347\247\273\351\231\244\351\223\276\350\241\250-\350\256\276\350\256\241\351\223\276\350\241\250\351\223\276\350\241\250\345\217\215\350\275\254\345\217\214\346\214\207\351\222\210\346\263\225\351\200\222\345\275\222\346\263\225/index.html" @@ -0,0 +1,533 @@ +【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法) +
Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)

【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)

算法任务:链表理论基础、leetcode203.移除链表元素、leetcode707.设计链表、leetcode206.反转链表

+
+

今日任务

  • 链表理论基础

  • 203.移除链表元素

  • 707.设计链表

  • 206.反转链表

1.链表理论基础

(1)什么是链表?

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

链表的入口节点称为链表的头节点也就是head。

(2)链表的类型

常见的链表类型有以下几种:

<1>单链表

单向链表是一种包含两部分的数据结构,即一个是数据部分(数据域),另一个是地址部分(指针域),其中包含下一个或后继节点的地址。节点中的地址部分也称为指针

image-20230217114232162

在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为头指针

由于单链表的指针域只保存了下一个节点的地址,因此在单链表中,只能向前遍历,而不能反向遍历

1
+2
+3
+4
+5
+6
+7
+
// 单向链表中节点的表示
+
+struct node 
+{ 
+int data; 
+struct node *next; 
+} 
+

<2>双链表

前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点

这就意味着,双向链表不仅支持向前查询,还可以向后查询

image-20230217114149969

1
+2
+3
+4
+5
+6
+7
+8
+
// 双向链表中节点的表示
+
+struct node 
+{ 
+int data; 
+struct node *next; 
+struct node *prev; 
+} 
+

<3>循环链表

循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,循环链表没有起始节点和结束节点,我们可以朝任意方向进行遍历(向前或者向后)。

image-20230217114529563

1
+2
+3
+4
+5
+6
+7
+
// 循环链表中节点的表示
+
+struct node 
+{ 
+int data; 
+struct node *next; 
+} 
+

乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。

(3)链表的存储方式

前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。

image-20230217120000271

在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。

(4)链表的定义

给出链表节点的定义:

1
+2
+3
+4
+5
+6
+
// 单链表
+strcut ListNode{
+	int val;	//节点上存储的元素
+	ListNode *next;		//指向下一个节点的指针
+	ListNode(int x): val(x),next(NULL){}	// 节点的构造函数
+};
+

下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):

1、通过自己定义构造函数初始化节点:

1
+
ListNode* head = new ListNode(5);
+

2、使用默认构造函数初始化节点:

1
+2
+
ListNode* head = new ListNode();
+head->val = 5;
+

从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。

(5)链表的操作

<1>删除节点

我们以下图为例,目的时删除D节点:

image-20230217142406253

具体操作:

C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要将C节点的next指针指向E节点就可以了

此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。

<2>添加节点

在下图中,我们需要在C节点和D节点中添加一个F节点:

image-20230217142827964

添加F节点,只需要将C节点的next指针指向F节点,同时F节点的next指针指向D节点,这样就完成了节点的添加。

(6)性能分析

这里我们将链表和数组做一个对比,详见下图:

image-20230217143205888

  • 数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。
  • 链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少

2.Leetcode203:移除链表元素

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements

(1)题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

image-20230217143757762

1
+2
+
输入:head = [1,2,6,3,4,5,6], val = 6
+输出:[1,2,3,4,5]
+

示例 2:

1
+2
+
输入:head = [], val = 1
+输出:[]
+

示例 3:

1
+2
+
输入:head = [7,7,7,7], val = 7
+输出:[]
+

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

(2)思路

案例1:

链表:1->4->2->4 目的:移除元素4

image-20230217144046231

其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。

image-20230217144342989

那么此外我们还需要完成节点4的内存回收工作!

案例二:

由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。

对于链表的操作有两种形式:

  • 1.直接使用原来的链表进行删除操作。
  • 2.设置一个虚拟头节点再进行删除操作。

<操作1>:直接使用原来的链表进行移除

移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。

那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。

image-20230217145654957

对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。

<操作2>:设置一个虚拟头节点再进行删除操作

如何设置虚拟头节点,首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4

image-20230217150125673

具体实现我们详见代码。

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+
// 操作1实现:直接使用原来的链表进行删除操作
+
+class Solution {
+public:
+    ListNode* removeElements(ListNode* head, int val) {
+        // 删除头结点
+        while (head != NULL && head->val == val) { 
+        // head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。
+            ListNode* tmp = head;
+            head = head->next;
+            delete tmp;		// 此处需要对旧的头节点进行内存回收
+        }
+
+        // 删除非头结点
+        ListNode* cur = head;	// 当前节点
+        while (cur != NULL && cur->next!= NULL) {
+        // cur->next!= NULL:这里是同样的道理,不可操作空指针
+            if (cur->next->val == val) {
+                ListNode* tmp = cur->next;
+                cur->next = cur->next->next;
+                delete tmp;
+            } else {
+                cur = cur->next;
+            }
+        }
+        return head;
+    }
+};
+

这里需要注意几点:

  • 对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错
  • 操作1的关键代码就是下面的这两部分

image-20230217153228463

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
// 操作2实现:设置一个虚拟头节点再进行删除操作
+
+class Solution {
+public:
+    ListNode* removeElements(ListNode* head, int val) {
+        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
+        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
+        ListNode* cur = dummyHead;
+        while (cur->next != NULL) {
+            if(cur->next->val == val) {
+                ListNode* tmp = cur->next;
+                cur->next = cur->next->next;
+                delete tmp;
+            } else {
+                cur = cur->next;
+            }
+        }
+        head = dummyHead->next;
+        delete dummyHead;
+        return head;
+    }
+};
+

3.Leetcode707:设计链表

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list

(1)题目

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

示例:

1
+2
+3
+4
+5
+6
+7
+
MyLinkedList linkedList = new MyLinkedList();
+linkedList.addAtHead(1);
+linkedList.addAtTail(3);
+linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
+linkedList.get(1);            //返回2
+linkedList.deleteAtIndex(1);  //现在链表是1-> 3
+linkedList.get(1);            //返回3
+

提示:

  • 0 <= index, val <= 1000
  • 请不要使用内置的 LinkedList 库。
  • get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。

(2)思路

分析题目给出的要求,主要是需要完成以下功能:

  • 获取链表第index个节点的值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点面前插入一个节点
  • 删除链表的第index个节点

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+
class MyLinkedList {
+public:
+    // 定义链表节点结构体
+    struct LinkedNode {
+        int val;
+        LinkedNode* next;
+        LinkedNode(int val):val(val), next(nullptr){}
+    };
+
+    // 初始化链表
+    MyLinkedList() {
+        _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
+        _size = 0;
+    }
+
+    // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
+    int get(int index) {
+        if (index > (_size - 1) || index < 0) {
+            return -1;
+        }
+        LinkedNode* cur = _dummyHead->next;
+        while(index--){ // 如果--index 就会陷入死循环
+            cur = cur->next;
+        }
+        return cur->val;
+    }
+
+    // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
+    // 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路
+    void addAtHead(int val) {
+        LinkedNode* newNode = new LinkedNode(val);
+        newNode->next = _dummyHead->next;
+        _dummyHead->next = newNode;
+        _size++;
+    }
+
+    // 在链表最后面添加一个节点
+    void addAtTail(int val) {
+        LinkedNode* newNode = new LinkedNode(val);
+        LinkedNode* cur = _dummyHead;
+        while(cur->next != nullptr){
+            cur = cur->next;
+        }
+        cur->next = newNode;
+        _size++;
+    }
+
+    // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
+    // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
+    // 如果index大于链表的长度,则返回空
+    // 如果index小于0,则在头部插入节点
+    void addAtIndex(int index, int val) {
+
+        if(index > _size) return;
+        if(index < 0) index = 0;        
+        LinkedNode* newNode = new LinkedNode(val);
+        LinkedNode* cur = _dummyHead;
+        while(index--) {
+            cur = cur->next;
+        }
+        newNode->next = cur->next;
+        cur->next = newNode;
+        _size++;
+    }
+
+    // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
+    void deleteAtIndex(int index) {
+        if (index >= _size || index < 0) {
+            return;
+        }
+        LinkedNode* cur = _dummyHead;
+        while(index--) {
+            cur = cur ->next;
+        }
+        LinkedNode* tmp = cur->next;
+        cur->next = cur->next->next;
+        delete tmp;
+        _size--;
+    }
+
+    // 打印链表
+    void printLinkedList() {
+        LinkedNode* cur = _dummyHead;
+        while (cur->next != nullptr) {
+            cout << cur->next->val << " ";
+            cur = cur->next;
+        }
+        cout << endl;
+    }
+private:
+    int _size;
+    LinkedNode* _dummyHead;
+
+};
+

4.Leetcode206:反转链表

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list

(1)题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

image-20230217163726826

1
+2
+
输入:head = [1,2,3,4,5]
+输出:[5,4,3,2,1]
+

示例 2:

image-20230217163749967

1
+2
+
输入:head = [1,2]
+输出:[2,1]
+

示例 3:

1
+2
+
输入:head = []
+输出:[]
+

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

(2)思路

链表的反转,只需要改变next指针的指向即可。

(3)双指针法

对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。

  • cur指针,指向链表的头节点
  • pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+
class Solution {
+public:
+    ListNode* reverseList(ListNode* head) {
+        ListNode* temp; // 作为一个临时节点,保存cur的下一个节点
+        ListNode* cur = head;
+        ListNode* pre = NULL;	// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL
+        // 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur
+        while(cur) {
+            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
+            cur->next = pre; // 翻转操作
+            // 更新pre 和 cur指针
+            pre = cur;
+            cur = temp;
+        }
+        return pre;	// 返回的是新链表的头节点pre
+    }
+};
+

(4)递归法

前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有自前向后递归、以及自后向前递归两种方法。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
// 递归法:自前向后
+
+class Solution {
+public:
+    ListNode* reverse(ListNode* pre,ListNode* cur){
+        if(cur == NULL) return pre;
+        ListNode* temp = cur->next;
+        cur->next = pre;
+        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
+        // pre = cur;
+        // cur = temp;
+        return reverse(cur,temp);
+    }
+    ListNode* reverseList(ListNode* head) {
+        // 和双指针法初始化是一样的逻辑
+        // ListNode* cur = head;
+        // ListNode* pre = NULL;
+        return reverse(NULL, head);
+    }
+
+};
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
// 递归法:自后向前
+
+class Solution {
+public:
+    ListNode* reverseList(ListNode* head) {
+        // 边缘条件判断
+        if(head == NULL) return NULL;
+        if (head->next == NULL) return head;
+        
+        // 递归调用,翻转第二个节点开始往后的链表
+        ListNode *last = reverseList(head->next);
+        // 翻转头节点与第二个节点的指向
+        head->next->next = head;
+        // 此时的 head 节点为尾节点,next 需要指向 NULL
+        head->next = NULL;
+        return last;
+    }
+}; 
+
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7.jpg" new file mode 100644 index 000000000..c5ba95b12 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_250x150_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..af765ed3f Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.e990eeffbd9dc987ea5711a62c4461c7_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.jpg" new file mode 100644 index 000000000..c5ba95b12 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_120x120_fill_q75_box_smart1.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..17cad8edf Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_1600x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ebda11ba3 Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_800x0_resize_q75_box.jpg" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ccc34c30c Binary files /dev/null and "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_800x0_resize_q75_box.jpg" differ diff --git "a/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/index.html" "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/index.html" new file mode 100644 index 000000000..949850d67 --- /dev/null +++ "b/p/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\351\223\276\350\241\2502\350\212\202\347\202\271\344\272\244\346\215\242\344\270\216\345\210\240\351\231\244-\351\223\276\350\241\250\347\233\270\344\272\244-\347\216\257\345\275\242\351\223\276\350\241\250/index.html" @@ -0,0 +1,328 @@ +【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表 +
Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表

【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表

算法任务:链表总结、leetcode24.两两交换链表中的节点、leetcode19.删除链表的倒数第N个节点、Leetcode面试题02.07.链表相交、Leetcode142.环形链表II

+
+

今日任务

  • 24.两两交换链表中的节点

  • 19.删除链表的倒数第N个节点

  • 面试题02.07.链表相交

  • 142.环形链表II

  • 总结

1.Leetcode24:两两交换链表中的节点

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs

(1)题目

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

image-20230218104104240

1
+2
+
输入:head = [1,2,3,4]
+输出:[2,1,4,3]
+

示例 2:

1
+2
+
输入:head = []
+输出:[]
+

示例 3:

1
+2
+
输入:head = [1]
+输出:[1]
+

提示:

  • 链表中节点的数目在范围 [0, 100] 内
  • 0 <= Node.val <= 100

(2)思路

前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:

  • 1.直接使用原来的链表进行删除操作。
  • 2.设置一个虚拟头节点再进行删除操作。

相比较第一种,第二种虚拟头节点的形式更加方便。

初始时,cur指向虚拟头节点,然后依次进行三步:

  • 步骤1:将原链表的头节点变成节点2
  • 步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)
  • 步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)
  • ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表

image-20230218111454677

操作后的链表:

image-20230218111528059

终止条件:

当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
class Solution {
+public:
+    ListNode* swapPairs(ListNode* head) {
+        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
+        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
+        ListNode* cur = dummyHead;
+        while(cur->next != nullptr && cur->next->next != nullptr) {
+            ListNode* tmp = cur->next; // 记录临时节点,原本的头节点
+            ListNode* tmp1 = cur->next->next->next; // 记录临时节点,原本的节点3
+
+            cur->next = cur->next->next;    // 步骤一
+            cur->next->next = tmp;          // 步骤二
+            cur->next->next->next = tmp1;   // 步骤三
+
+            cur = cur->next->next; // cur移动两位,准备下一轮交换
+        }
+        return dummyHead->next;
+    }
+};
+

2.Leetcode19:删除链表的倒数第N个节点

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list

(1)题目

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

image-20230218114024717

1
+2
+
输入:head = [1,2,3,4,5], n = 2
+输出:[1,2,3,5]
+

示例 2:

1
+2
+
输入:head = [1], n = 1
+输出:[]
+

示例 3:

1
+2
+
输入:head = [1,2], n = 1
+输出:[1]
+

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

进阶:你能尝试使用一趟扫描实现吗?

(2)思路

先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow->next = slow->next->next即可完成对目标节点的删除。

同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。

<1>首先定义fast指针和slow指针,初始值为虚拟头节点:

image-20230218115133608

<2>fast走n+1步(因为加入了虚拟头节点)

image-20230218115254196

<3>fast和slow同时移动,直到fast指向链表末

image-20230218115341005

<4>删除slow指向的下一个节点

image-20230218115452233

(3)快慢指针法

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
class Solution {
+public:
+    ListNode* removeNthFromEnd(ListNode* head, int n) {
+        ListNode* dummyHead = new ListNode(0);
+        dummyHead->next = head;
+        ListNode* slow = dummyHead;
+        ListNode* fast = dummyHead;
+        while(n-- && fast != NULL) {	// 让fast指向目标节点
+            fast = fast->next;
+        }
+        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
+        while (fast != NULL) {
+            fast = fast->next;
+            slow = slow->next;
+        }
+        slow->next = slow->next->next; 
+        
+        // ListNode *tmp = slow->next;  C++释放内存的逻辑
+        // slow->next = tmp->next;
+        // delete nth;
+        
+        return dummyHead->next;
+    }
+};
+

3.Leetcode面试题02.07:链表相交

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci

(1)题目

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

image-20230218151939703

题目数据保证整个链式结构中不存在环。

注意,函数返回结果后,链表必须保持其原始结构 。

示例 1:

1
+2
+3
+4
+5
+
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
+输出:Intersected at '8'
+解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
+从各自的表头开始算起,链表 A  [4,1,8,4,5],链表 B  [5,0,1,8,4,5]
+ A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
+

示例 2:

1
+2
+3
+4
+5
+
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
+输出:Intersected at '2'
+解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
+从各自的表头开始算起,链表 A  [0,9,1,2,4],链表 B  [3,2,4]
+ A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
+

示例 3:

1
+2
+3
+4
+5
+
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
+输出:null
+解释:从各自的表头开始算起,链表 A  [2,6,4],链表 B  [1,5]
+由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA  skipB 可以是任意值。
+这两个链表不相交,因此返回 null 
+

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]

进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?

(2)思路

根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。

那么在算法中如何实现呢,那么只需要先分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键所在啦。

先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。

image-20230218161958873

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
class Solution {
+public:
+    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
+        ListNode* curA = headA;
+        ListNode* curB = headB;
+        int lenA = 0, lenB = 0;
+        while (curA != NULL) { // 求链表A的长度
+            lenA++;
+            curA = curA->next;
+        }
+        while (curB != NULL) { // 求链表B的长度
+            lenB++;
+            curB = curB->next;
+        }
+        curA = headA;
+        curB = headB;
+        // 让curA为最长链表的头,lenA为其长度
+        if (lenB > lenA) {
+            swap (lenA, lenB);
+            swap (curA, curB);
+        }
+        // 求长度差
+        int gap = lenA - lenB;
+        // 让curA和curB在同一起点上(末尾位置对齐)
+        while (gap--) {
+            curA = curA->next;
+        }
+        // 遍历curA 和 curB,遇到相同则直接返回
+        while (curA != NULL) {
+            if (curA == curB) {
+                return curA;
+            }
+            curA = curA->next;
+            curB = curB->next;
+        }
+        return NULL;
+    }
+};
+
  • 时间复杂度:O(n+m)
  • 空间复杂度:O(1)

4.Leetcode142:环形链表II

来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii

(1)题目

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改链表。

示例 1:

image-20230218163000655

1
+2
+3
+
输入:head = [3,2,0,-4], pos = 1
+输出:返回索引为 1 的链表节点
+解释:链表中有一个环,其尾部连接到第二个节点。
+

示例 2:

image-20230218163029607

1
+2
+3
+
输入:head = [1,2], pos = 0
+输出:返回索引为 0 的链表节点
+解释:链表中有一个环,其尾部连接到第一个节点。
+

示例 3:

image-20230218163050685

1
+2
+3
+
输入:head = [1], pos = -1
+输出:返回 null
+解释:链表中没有环。
+

提示:

  • 链表中节点的数目范围在范围 [0, 104] 内
  • -105 <= Node.val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引

进阶:你是否可以使用 O(1) 空间解决此题?

(2)思路

对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。

对于这道题我们需要解决以下两点:

  • 如何判断链表有环
  • 如果有环,怎么找到这个环的入口

<1>如何判断链表有环

对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点,如果fast指针和slow指针在中途相遇,则说明存在环形链表。

由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:

141.环形链表

<2>如果有环,怎么找到这个环的入口

既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。

假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。

image-20230218173510617

当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果,那么据此我们可以得出以下结论:

1.slow指针走过的节点数 = x + y

2.fast指针走过的节点数 = x + y + n*(y+z) n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数

3.得到等式:x + y = x + y + n*(y+z) 此处需要注意:n >= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍

4.我们的目标为x,因此化简上式:x = n (y + z) - y

5.当n等于1时,我们可以得知上式结果为:x = z,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。

6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点

动画如下:

142.环形链表II(求入口)

上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?

其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。

(3)代码实现

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+
/**
+ * Definition for singly-linked list.
+ * struct ListNode {
+ *     int val;
+ *     ListNode *next;
+ *     ListNode(int x) : val(x), next(NULL) {}
+ * };
+ */
+class Solution {
+public:
+    ListNode *detectCycle(ListNode *head) {
+        ListNode* fast = head;
+        ListNode* slow = head;
+        while(fast != NULL && fast->next != NULL) {
+            slow = slow->next;
+            fast = fast->next->next;
+            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
+            if (slow == fast) {
+                ListNode* index1 = fast;
+                ListNode* index2 = head;
+                while (index1 != index2) {
+                    index1 = index1->next;
+                    index2 = index2->next;
+                }
+                return index2; // 返回环的入口
+            }
+        }
+        return NULL;
+    }
+};
+

5.链表总结

image-20230218181324408

图片来源: 代码随想录知识星球成员:海螺人

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f8d077909 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/index.html" "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/index.html" new file mode 100644 index 000000000..0d7c3998a --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadart-pi-\347\275\221\347\273\234\346\227\266\351\222\237/index.html" @@ -0,0 +1,1129 @@ +ART-Pi 网络时钟 +
Featured image of post ART-Pi 网络时钟

ART-Pi 网络时钟

自制网络时钟,实现云端天气及实时时间获取

+
+

《玩转RT-Thread》自制网络时钟


@[toc]

一、准备工作

  • 开发平台:RT-Thread Studio

  • 开发板:ART-PI

  • 主控芯片:STM32H750

  • 温湿度传感器:SHT30

  • 显示模组:0.96’OLED(SSD1306)

  • 串口调试助手:SecureCRT

注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。

二、新建RT-Thread 项目

在这里插入图片描述

在这里插入图片描述

三、获取温湿度数据

1、双击打开左边导航栏的RT-Thread Setting

在这里插入图片描述

2、使能软件模拟i2c(单击点亮即可)

3、配置i2c及相关引脚

这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置

4、添加SHT3X软件包

CTRL+S保存配置,点击编译并下载

具体RT-Thread Studio的一般使用可参照【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)

此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功

此时在串口输入help,可以看出有一个sht3x配置

在这里插入图片描述

1
+2
+3
+
输入:
+sht3x probe i2c3 pd
+sht3x read(读取温湿度信息)
+

四、获取NTP时间

1、使能选择WiFi框架

2、使能AP6212库

3、添加easyflash和netutils软件包

在这里插入图片描述

鼠标右键netutils打开配置项

在这里插入图片描述

使能NTP (网络时间协议)客户端

使能软件模拟RTC

CTRL+S保存配置

修改配置

1
+2
+3
+4
+
(1)打开电脑中项目所在的路径-workpace-项目名称-packages-EasyFlash-v4.1.0-port,将port目录下的ef_fal_port.c文件复制到workpace-项目名称-board-port中
+
+(2)修改port中宏定义FAL_EF_PART_NAME 中的名字
+#define FAL_EF_PART_NAME "easyflash" //修改后的宏定义
+

此时再编译并下载到开发板中

4、连接WiFi

1
+2
+3
+4
+5
+
wifi scan     //搜索wifi
+wifi join [SSID] [PASSWORD]     //连接WiFi
+    
+SSID:WiFi名称
+PASSWORDWiFi密码
+

5、设置开机自连接WiFi

(1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+
/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-06-09     ASUS       the first version
+ */
+#include <rtthread.h>
+
+#ifdef BSP_USING_WIFI
+
+#include <wlan_mgnt.h>
+#include <wlan_cfg.h>
+#include <wlan_prot.h>
+
+#include <easyflash.h>
+#include <fal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if (EF_SW_VERSION_NUM < 0x40000)
+
+static char *str_base64_encode_len(const void *src, char *out, int input_length);
+static int   str_base64_decode(const char *data, int input_length, char *decoded_data);
+
+static const unsigned char base64_table[65] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char base64_decode_table[256] =
+{
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static char *str_base64_encode_len(const void *src, char *out, int len)
+{
+    unsigned char *pos;
+    const unsigned char *end, *in;
+    size_t olen;
+
+    olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
+    olen += olen / 72; /* line feeds */
+    olen++; /* nul termination */
+
+    end = (const unsigned char *)src + len;
+    in = (const unsigned char *)src;
+    pos = (unsigned char *)out;
+    while (end - in >= 3)
+    {
+        *pos++ = base64_table[in[0] >> 2];
+        *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
+        *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
+        *pos++ = base64_table[in[2] & 0x3f];
+        in += 3;
+    }
+
+    if (end - in)
+    {
+        *pos++ = base64_table[in[0] >> 2];
+
+        if (end - in == 1)
+        {
+            *pos++ = base64_table[(in[0] & 0x03) << 4];
+            *pos++ = '=';
+        }
+        else
+        {
+            *pos++ = base64_table[((in[0] & 0x03) << 4) |
+                                                  (in[1] >> 4)];
+            *pos++ = base64_table[(in[1] & 0x0f) << 2];
+        }
+        *pos++ = '=';
+    }
+
+    *pos = '\0';
+    return (char *)out;
+}
+
+/*
+ * return: length, 0 is error.
+ */
+static int str_base64_decode(const char *data, int input_length, char *decoded_data)
+{
+    int out_len;
+    int i, j;
+
+    if (input_length % 4 != 0) return 0;
+
+    out_len = input_length / 4 * 3;
+
+    if (data[input_length - 1] == '=') out_len--;
+    if (data[input_length - 2] == '=') out_len--;
+
+    for (i = 0, j = 0; i < input_length;)
+    {
+        uint32_t sextet_a = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
+        uint32_t sextet_b = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
+        uint32_t sextet_c = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
+        uint32_t sextet_d = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
+
+        uint32_t triple = (sextet_a << 3 * 6)
+                          + (sextet_b << 2 * 6)
+                          + (sextet_c << 1 * 6)
+                          + (sextet_d << 0 * 6);
+
+        if (j < out_len) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
+        if (j < out_len) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
+        if (j < out_len) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
+    }
+
+    return out_len;
+}
+
+static int read_cfg(void *buff, int len)
+{
+    char *wlan_cfg_info = RT_NULL;
+
+    wlan_cfg_info = ef_get_env("wlan_cfg_info");
+    if (wlan_cfg_info != RT_NULL)
+    {
+        str_base64_decode(wlan_cfg_info, rt_strlen(wlan_cfg_info), buff);
+        return len;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static int get_len(void)
+{
+    int len;
+    char *wlan_cfg_len = RT_NULL;
+
+    wlan_cfg_len = ef_get_env("wlan_cfg_len");
+    if (wlan_cfg_len == RT_NULL)
+    {
+        len = 0;
+    }
+    else
+    {
+        len = atoi(wlan_cfg_len);
+    }
+
+    return len;
+}
+
+static int write_cfg(void *buff, int len)
+{
+    char wlan_cfg_len[12] = {0};
+    char *base64_buf = RT_NULL;
+
+    base64_buf = rt_malloc(len * 4 / 3 + 4); /* 3-byte blocks to 4-byte, and the end. */
+    if (base64_buf == RT_NULL)
+    {
+        return -RT_ENOMEM;
+    }
+    rt_memset(base64_buf, 0, len);
+
+    /* interger to string */
+    sprintf(wlan_cfg_len, "%d", len);
+    /* set and store the wlan config lengths to Env */
+    ef_set_env("wlan_cfg_len", wlan_cfg_len);
+    str_base64_encode_len(buff, base64_buf, len);
+    /* set and store the wlan config information to Env */
+    ef_set_env("wlan_cfg_info", base64_buf);
+    ef_save_env();
+    rt_free(base64_buf);
+
+    return len;
+}
+
+#else
+
+static int read_cfg(void *buff, int len)
+{
+    size_t saved_len;
+
+    ef_get_env_blob("wlan_cfg_info", buff, len, &saved_len);
+    if (saved_len == 0)
+    {
+        return 0;
+    }
+
+    return len;
+}
+
+static int get_len(void)
+{
+    int len;
+    size_t saved_len;
+
+    ef_get_env_blob("wlan_cfg_len", &len, sizeof(len), &saved_len);
+    if (saved_len == 0)
+    {
+        return 0;
+    }
+
+    return len;
+}
+
+static int write_cfg(void *buff, int len)
+{
+    /* set and store the wlan config lengths to Env */
+    ef_set_env_blob("wlan_cfg_len", &len, sizeof(len));
+
+    /* set and store the wlan config information to Env */
+    ef_set_env_blob("wlan_cfg_info", buff, len);
+
+    return len;
+}
+
+#endif /* (EF_SW_VERSION_NUM < 0x40000) */
+
+static const struct rt_wlan_cfg_ops ops =
+{
+    read_cfg,
+    get_len,
+    write_cfg
+};
+
+void wlan_autoconnect_init(void)
+{
+    fal_init();
+    easyflash_init();
+
+    rt_wlan_cfg_set_ops(&ops);
+    rt_wlan_cfg_cache_refresh();
+}
+
+#endif
+

(2)在main.c中添加自动连接函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+
#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_common.h"
+
+#define LED_PIN GET_PIN(I, 8)
+extern void wlan_autoconnect_init(void);
+
+int main(void)
+{
+    rt_uint32_t count = 1;
+
+    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
+    /* init Wi-Fi auto connect feature */
+    wlan_autoconnect_init();
+    /* enable auto reconnect on WLAN device */
+    rt_wlan_config_autoreconnect(RT_TRUE);
+
+    return RT_EOK;
+}
+
+#include "stm32h7xx.h"
+static int vtor_config(void)
+{
+    /* Vector Table Relocation in Internal QSPI_FLASH */
+    SCB->VTOR = QSPI_BASE;
+    return 0;
+}
+INIT_BOARD_EXPORT(vtor_config);
+

编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。

五、OLED屏显示温湿度和实时时间信息

1、添加u8g2软件包

2、编写oled_display显示线程

(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。

代码如下:

  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+
#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <U8g2lib.h>
+#include <stdio.h>
+#include <board.h>	
+#include "drv_common.h"
+
+#include <drv_soft_i2c.h>
+
+extern "C"
+{
+#include <sht3x.h>
+}
+extern "C"
+{
+sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr);
+rt_err_t sht3x_read_singleshot(sht3x_device_t dev);
+}
+
+#define OLED_I2C_PIN_SCL                    24 //
+#define OLED_I2C_PIN_SDA                    25  //
+
+static U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,\
+                                         /* clock=*/ OLED_I2C_PIN_SCL,\
+                                         /* data=*/ OLED_I2C_PIN_SDA,\
+                                         /* reset=*/ U8X8_PIN_NONE);
+
+#define SUN 0
+#define SUN_CLOUD  1
+#define CLOUD 2
+#define RAIN 3
+#define THUNDER 4
+
+static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol)
+{
+  // fonts used:
+  // u8g2_font_open_iconic_embedded_6x_t
+  // u8g2_font_open_iconic_weather_6x_t
+  // encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic
+
+  switch(symbol)
+  {
+    case SUN:
+      u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
+      u8g2.drawGlyph(x, y, 69);
+      break;
+    case SUN_CLOUD:
+      u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
+      u8g2.drawGlyph(x, y, 65);
+      break;
+    case CLOUD:
+      u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
+      u8g2.drawGlyph(x, y, 64);
+      break;
+    case RAIN:
+      u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
+      u8g2.drawGlyph(x, y, 67);
+      break;
+    case THUNDER:
+      u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t);
+      u8g2.drawGlyph(x, y, 67);
+      break;
+  }
+}
+
+static void drawWeather(uint8_t symbol, int degree)
+{
+  drawWeatherSymbol(0, 63, symbol);
+  u8g2.setFont(u8g2_font_logisoso32_tf);
+  u8g2.setCursor(55, 63);
+  u8g2.print(degree);
+  u8g2.print("C");
+}
+static void drawHumidity(uint8_t symbol, int humidity)
+{
+  drawWeatherSymbol(0, 63, symbol);
+  u8g2.setFont(u8g2_font_logisoso32_tf);
+  u8g2.setCursor(55, 63);
+  u8g2.print(humidity);
+  u8g2.print("%");
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void oled_display()
+{
+    u8g2.begin();
+    u8g2.clearBuffer();
+
+    u8g2.setFont(u8g2_font_logisoso32_tf);
+    u8g2.setCursor(48+3, 42);
+    u8g2.print("Hi~");     // requires enableUTF8Print()
+
+    u8g2.setFont(u8g2_font_6x13_tr);            // choose a suitable font
+    u8g2.drawStr(30, 60, "By Mculover666");   // write something to the internal memory
+    u8g2.sendBuffer();
+
+    sht3x_device_t  sht3x_device;
+    sht3x_device = sht3x_init("i2c3", 0x44);
+
+    rt_thread_mdelay(2000);
+
+    int status = 0;
+    char mstr[3];
+    char hstr[3];
+    time_t now;
+    struct tm *p;
+    int min = 0, hour = 0;
+    int temperature = 0,humidity = 0;
+
+    while(1)
+    {
+        switch(status)
+        {
+            case 0:
+                now = time(RT_NULL);
+                p=gmtime((const time_t*) &now);
+                hour = p->tm_hour;
+                min = p->tm_min;
+                sprintf(mstr, "%02d", min);
+                sprintf(hstr, "%02d", hour);
+
+
+                u8g2.firstPage();
+                do {
+                     u8g2.setFont(u8g2_font_logisoso42_tn);
+                     u8g2.drawStr(0,63,hstr);
+                     u8g2.drawStr(50,63,":");
+                     u8g2.drawStr(67,63,mstr);
+                   } while ( u8g2.nextPage() );
+
+
+                rt_thread_mdelay(5000);
+                status = 1;
+                break;
+           case 1:
+               if(RT_EOK == sht3x_read_singleshot(sht3x_device))
+               {
+                   temperature = (int)sht3x_device->temperature;
+               }
+               else
+               {
+                   temperature = 0;
+               }
+               u8g2.clearBuffer();
+               drawWeather(SUN, temperature);
+               u8g2.sendBuffer();
+               rt_thread_mdelay(5000);
+               status = 2;
+               break;
+           case 2:
+               if(RT_EOK == sht3x_read_singleshot(sht3x_device))
+              {
+                   humidity = (int)sht3x_device->humidity;
+              }
+              else
+              {
+                  humidity = 0;
+              }
+              u8g2.clearBuffer();
+              drawHumidity(RAIN, humidity);
+              u8g2.sendBuffer();
+              rt_thread_mdelay(5000);
+              status = 0;
+              break;
+        }
+    }
+}
+MSH_CMD_EXPORT(oled_display, oled start);
+
+#ifdef __cplusplus
+}
+#endif
+

(2)在 applications 文件夹下创建oled_display.h

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-06-09     ASUS       the first version
+ */
+#ifndef APPLICATIONS_OLED_DISPLAY_H_
+#define APPLICATIONS_OLED_DISPLAY_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void oled_display(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APPLICATIONS_OLED_DISPLAY_H_ */
+

(3)最终的主函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-09-02     RT-Thread    first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_common.h"
+
+extern void wlan_autoconnect_init(void);
+
+int main(void)
+{
+    rt_uint32_t count = 1;
+
+    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
+
+    wlan_autoconnect_init();
+
+    rt_wlan_config_autoreconnect(RT_TRUE);
+
+    oled_display();
+
+    return RT_EOK;
+}
+
+#include "stm32h7xx.h"
+static int vtor_config(void)
+{
+    /* Vector Table Relocation in Internal QSPI_FLASH */
+    SCB->VTOR = QSPI_BASE;
+    return 0;
+}
+INIT_BOARD_EXPORT(vtor_config);
+

(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+
/*-------------------------- I2C CONFIG BEGIN --------------------------*/
+
+#ifdef BSP_USING_I2C1
+#define BSP_I2C1_SCL_PIN    24 // p2 10 PB8
+#define BSP_I2C1_SDA_PIN    25 // p2 7 PB9
+#endif
+
+#ifdef BSP_USING_I2C3
+#define BSP_I2C3_SCL_PIN    119 //p1 29 PH7
+#define BSP_I2C3_SDA_PIN    120 //p1 28 PH8
+#endif
+
+/*-------------------------- UART CONFIG END --------------------------*/
+

六、实验展示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

七、问题总结

注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// cpp函数
+
+#ifdef __cplusplus
+}
+#endif
+

在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。


这次的分享就到这里,有相关问题的欢迎留言私信!

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 22, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f8d077909 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/index.html" "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/index.html" new file mode 100644 index 000000000..684106bb4 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadcpk-ra6m4\346\231\272\346\205\247\351\227\250\347\246\201\347\263\273\347\273\237\346\225\231\345\255\246/index.html" @@ -0,0 +1,316 @@ +CPK-RA6M4智慧门禁系统教学 +
Featured image of post CPK-RA6M4智慧门禁系统教学

CPK-RA6M4智慧门禁系统教学

本视频秉持着学习开放的思想,在RT-Thread夏令营经历的这几周时间,自己也是结合所学知识开发出一款智慧门禁系统,而为了大家更好的学习交流,本次将以视频录制加源码开源的方式供大家学习参考。

+
+

image-20220804171524901

1、项目介绍

本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。

下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。

2、前期准备

开发工具:

  • RT-Thread Studio

在这里插入图片描述

RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。

RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。

下载链接:RT-Thread Studio 下载

  • 瑞萨FSP(灵活配置软件包)

Flexible Software Package (FSP)

瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。

下载链接:瑞萨FSP v3.5.0

模块:

  • AHT10
  • ESP8266
  • RC522及读卡标签
  • ssd1306 OLED显示屏

3、模块介绍及使用

3.1 AHT10

3.1.1底层I2C通信协议简介

I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。

而I2C通信的读写数据是通过等待从机的应答信号(ACK)。

也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。

这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。

当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。

简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。

3.1.2 sensor框架的使用

在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。

掌握sensor框架的使用,需要了解一下API的调用:

函数描述
rt_device_find()根据传感器设备设备名称查找设备获取设备句柄
rt_device_open()打开传感器设备
rt_device_read()读取数据
rt_device_control()控制传感器设备
rt_device_set_rx_indicate()设置接收回调函数
rt_device_close()关闭传感器设备
3.1.3 AHT10对接到sensor框架

首先先来介绍下接线:

引脚功能引脚接线
SCLP512
SDAP511
VCC3.3V
GNDGND

然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动->Enable I2C BUS->使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能

image-20220805110607476

然后使用下面的程序完成模块初始化工作

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+
#include "sensor_asair_aht10.h"
+#define AHT10_I2C_BUS  "i2c1"
+
+/* 模块初始化工作 */
+static int rt_hw_aht10_port(void)
+{
+    struct rt_sensor_config cfg;
+    cfg.intf.dev_name  = AHT10_I2C_BUS;
+    cfg.intf.user_data = (void *)AHT10_I2C_ADDR;
+    rt_hw_aht10_init("aht10", &cfg);
+    return RT_EOK;
+}
+INIT_ENV_EXPORT(rt_hw_aht10_port);
+

AHT10温湿度数据读取

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
    // AHT10设备读取数值
+    float humidity, temperature;
+
+    aht10_device_t dev;
+    rt_hw_aht10_port();
+    dev = aht10_init(AHT10_I2C_BUS);
+    if (dev == RT_NULL)
+    {
+        rt_kprintf(" The sensor initializes failure");
+    }
+    else
+    {
+        rt_kprintf(" The sensor initializes ok!\n");
+    }
+    
+    /* read humidity 采集湿度 */
+    humidity = aht10_read_humidity(dev);
+    /* read temperature 采集温度 */
+    temperature = aht10_read_temperature(dev);
+

3.2 ESP8266

3.2.1 底层uart简介

UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。

UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。

  • 串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。
  • 异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。
  • 数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。

查看源图像

空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。

起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。

数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。

3.2.2 MQTT通讯协议介绍

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。

其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。

在这里插入图片描述

3.2.3 AT组件

AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:

在这里插入图片描述

由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。

3.2.4 MQTT协议及AT组件在RT-Thread中的使用

RT-Thread Settings设置

添加AT Device及OneNET软件包

AT Device配置:

image-20220805122341394

OneNET配置:

首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。

image-20220805122741348 +image-20220805122836636

然后将创建的信息填写到settings中

image-20220805123248475

在组件中使能AT命令

image-20220805123407687

接线示意:

引脚功能引脚接线
TXP100
RXP101
VCC5V
GNDGND

FSP配置

由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置

首先点击RA Smart Configurator,记住这里使用的FSP版本为v3.5.0

image-20220805152204348

image-20220805153017364

image-20220805153317144

image-20220805153416015

完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现#include <dfs_posix.h>未参与编译以及还有其他一些问题,可以参考这一issue[CPK-RA6M4] onenet上云报错<RT-Thread 的版本为 4.1.0 及以上>

现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。

然后就是数据上云,代码如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
            if (onenet_mqtt_upload_digit("temperature",temperature) < 0)
+            {
+                LOG_E("upload has an error, stop uploading");
+            }
+            else
+            {
+                rt_kprintf("humidity : %d.%d\n", (int)temperature, (int)(temperature * 10) % 10);
+            }
+
+            rt_thread_delay(5000);
+
+
+            if (onenet_mqtt_upload_digit("humidity",humidity ) < 0)
+            {
+                LOG_E("upload has an error, stop uploading");
+            }
+            else
+            {
+                rt_kprintf("humidity : %d.%d\n", (int)humidity, (int)(humidity * 10) % 10);
+            }
+

这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。

image-20220805145942277

image-20220805145958887

3.3 RC522

3.3.1 底层SPI协议简介

SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:

SPI 主设备和从设备的连接方式

  • MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。
  • MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。
  • SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。
  • CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。

整体的传输大概可以分为以下几个过程:

(1)主机先将NSS信号拉低,这样保证开始接收数据;

(2)当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit;由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度。

(3)主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;

(4)主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;

查看源图像

3.3.2 RC522读卡机制说明

首先来看下RC522与M1卡的通讯流程:

寻卡->防止卡片冲撞->选卡->休眠->发送0x40(7bit)->发送0x43->发送0xa0等4字节->发送0x00等18字节

image-20220805154320392

  • 复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。

  • 防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。

  • 选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。

  • 三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。

  • 对数据块的操作: +读(Read):读一个块的数据; +写(Write):在一个块中写数据; +加(Increment):对数据块中的数值进行加值; +减(Decrement):对数据块中的数值进行减值; +传输(Transfer):将数据寄存器中的内容写入数据块中; +中止(Halt):暂停卡片的工作;

3.3.3 RC522在RT-Thread的使用

首先打开settings,添加RC522软件包,并在硬件部分使能SPI1

image-20220805155052783

打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:

image-20220805155448374

引脚接线:

引脚功能引脚接线
MOSIP411
MISOP410
SCLP412
SDAP311
RSTP312
VCC3.3V
GNDGND
IRQ悬空

代码部分参考RC522sample

image-20220805155715593

SPI初始化配置:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+
#include "mfrc522.h"
+
+static struct rt_spi_device mfrc522_spi_dev;
+struct rt_hw_spi_cs
+{
+    rt_uint32_t pin;
+};
+static struct rt_hw_spi_cs spi_cs;
+
+static int rt_hw_spi_rc522_init()
+{
+    rt_err_t res = RT_EOK;
+
+    // Attach Device
+    spi_cs.pin = MFRC522_SS_PIN;
+    rt_pin_mode(spi_cs.pin, PIN_MODE_OUTPUT);
+    res = rt_spi_bus_attach_device(&mfrc522_spi_dev, MFRC522_SPI_DEVICE_NAME, MFRC522_SPI_BUS_NAME, (void*)&spi_cs);
+    if (res != RT_EOK)
+    {
+        rt_kprintf("[RC522] Failed to attach device %s\n", MFRC522_SPI_DEVICE_NAME);
+        return res;
+    }
+
+    // Set device SPI Mode
+    struct rt_spi_configuration cfg = {0};
+    cfg.data_width = 8;
+    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS;
+    cfg.max_hz = MFRC522_SPICLOCK;
+
+    rt_spi_configure(&mfrc522_spi_dev, &cfg);
+
+    return RT_EOK;
+}
+/* 导出到自动初始化 */
+INIT_COMPONENT_EXPORT(rt_hw_spi_rc522_init);
+

另外需要在完成一下配置,双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚

image-20220805155922942

打开mfrc522.c,修改配置MFRC522_SS_PINMFRC522_RST_PIN

image-20220805161330936

打开rtconfig.h,找到以下两个引脚的定义,修改成如下:

注意:一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置

1
+2
+
#define MFRC522_SS_PIN 0x3b
+#define MFRC522_RST_PIN 0x3c
+

至此,RC522的相关配置结束

3.4 SSD1306

3.4.1 底层I2C通信协议

(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)

3.4.2 SSD1306在RT-Thred的使用

接线示意:

引脚功能引脚接线
SCLP400
SDAP401
VCC3.3V
GNDGND

RT-Thread Settings配置:

添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0

image-20220805162320450

打开rtconfig.h,添加i2c代码,注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码

1
+2
+3
+4
+
#define BSP_USING_I2C
+#define BSP_USING_I2C0
+#define BSP_I2C0_SCL_PIN 0x400
+#define BSP_I2C0_SDA_PIN 0x401
+

打开drv_soft_i2c.c文件,添加代码:

1
+2
+3
+4
+5
+6
+7
+8
+
#ifdef BSP_USING_I2C0
+#define I2C0_BUS_CONFIG                                  \
+    {                                                    \
+        .scl = BSP_I2C0_SCL_PIN,                         \
+        .sda = BSP_I2C0_SDA_PIN,                         \
+        .bus_name = "i2c0",                              \
+    }
+#endif
+

打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:

image-20220805162941069

生成配置之后添加用户代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
#include "ssd1306.h"
+
+void oled_init()
+{
+    ssd1306_Init();
+
+    ssd1306_Fill(Black);
+    ssd1306_SetCursor(10, 25);
+    ssd1306_WriteString("Hello RT-Thread!", Font_7x10, White);
+    ssd1306_UpdateScreen();
+}
+INIT_APP_EXPORT(oled_init);
+

实时时钟显示代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
            ssd1306_Fill(White);
+            ssd1306_SetCursor(0, 5);
+            ssd1306_WriteString("Now Time", Font_16x26, Black);
+            ssd1306_SetCursor(40, 40);
+            ssd1306_WriteString(mstr, Font_11x18, Black);
+            ssd1306_SetCursor(50, 40);
+            ssd1306_WriteString(":", Font_11x18, Black);
+            ssd1306_SetCursor(60, 40);
+            ssd1306_WriteString(hstr, Font_11x18, Black);
+            ssd1306_UpdateScreen();
+

温湿度数据显示代码:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
            ssd1306_Fill(White);
+            ssd1306_SetCursor(4, 2);
+            ssd1306_WriteString("Humi_Temp_Detection!", Font_7x10, Black);
+            ssd1306_UpdateScreen();
+
+            rt_thread_mdelay(1000);
+            char buff[64];
+
+            snprintf(buff, sizeof(buff), "Temperature: %d.%d\n", (int)temperature, (int)(temperature * 10) % 10);
+            ssd1306_SetCursor(15, 30);
+            ssd1306_WriteString(buff, Font_6x8, Black);
+            ssd1306_UpdateScreen();
+            rt_kprintf("Temperature_OLED : %d.%d\n", (int)temperature, (int)(temperature * 10) % 10);
+
+            snprintf(buff, sizeof(buff), "Humidity:%d.%d\n", (int)humidity, (int)(humidity * 10) % 10);
+            ssd1306_SetCursor(25, 47);
+            ssd1306_WriteString(buff, Font_6x8, Black);
+            ssd1306_UpdateScreen();
+            rt_kprintf("Humidity_OLED : %d.%d\n", (int)humidity, (int)(humidity * 10) % 10);
+

4、整体代码框架

4.1 多线程任务分配

本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。

所以共创建四个线程:

(1)RC522_thread:用于RC522读卡

(2)aht10_read_thread:用于aht10读取温湿度数值

(3)onenet_aht10_thread:云端数据上报

(4)oled_thread:OLED显示

4.2 线程间交互

本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。

4.3 代码整合

image-20220802210559475

在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。

都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。

image-20220805171602257

5、踩坑指南

其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:

(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为v3.5.0

(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。

(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 24, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/index.html" "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..bbf07b79b --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadenv\345\267\245\345\205\267\345\255\246\344\271\240/index.html" @@ -0,0 +1,51 @@ +env工具学习 +
Featured image of post env工具学习

env工具学习

Env 是 RT-Thread 推出的开发辅助工具,包括配置器和包管理器。开发者可以使用 Env 工具对 RT-Thread 内核和组件的功能进行配置,对组件进行自由裁剪,对线上软件包进行管理,使得系统以搭积木的方式进行构建,简单方便。

+
+

一、基础配置

1.首先需要下载git并配置好相应的环境变量

2.双击env,在setting中设置

在这里插入图片描述

这样就可以指定文件夹打开env工具了

二、基本命令学习

1.scons:编译

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]

(1)scons:编译并打印相关内部信息 +(2)scons -c:清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +(3)scons -s:编译而不打印具体的内部命令 +(4)scons --target=XXX:使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载

1
+2
+3
+
scons --target=iar
+scons --target=mdk4
+scons --target=mdk5
+

(5)scons -jN:多线程编译目标,在多核计算机上可以使用此命令加快编译速度

1
+
scons -j4 //双核编译工程
+

注意:一般不建议使用,容易将编译信息和错误混杂 +(6)scons --dist:搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径

1
+2
+
set RTT_CC=keil
+set RTT_EXEC_PATH=C:/Keilv5
+

3.menuconfig +打开菜单配置界面,可用户自定义模块

4.scons进阶学习 +scons内置函数

  • GetCurrentDir(): +获取当前路径。

  • Glob(’*.c’): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。

  • GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。

  • Split(str): +将字符串 str 分割成一个列表 list。

  • DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +DefineGroup() 函数的参数描述:

参数描述
nameGroup 的名字
srcGroup 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件
dependGroup 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现
parameters配置其他参数,可取值见下表,实际使用时不需要配置所有参数

parameters可加入的参数:

参数描述
dirsSConscript 文件路径
variant_dir指定生成的目标文件的存放路径
duiplicate设定是否拷贝或链接源文件到 variant_dir
+Licensed under CC BY-NC-SA 4.0
+Last updated on May 12, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/index.html" "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..c4fa8d320 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadi2c\345\206\205\346\240\270\345\255\246\344\271\240/index.html" @@ -0,0 +1,408 @@ +I2C(内核学习) +
Featured image of post I2C(内核学习)

I2C(内核学习)

I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。

+
+

一、i2c协议

由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。

二、i2c物理层

  • i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 +SDA:用于传输数据 +SCL:用于同步数据收发

  • 每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问

  • i2c支持多主控,任何时间点都只能有一个主控。 +在这里插入图片描述

  • i2c器件的SDA引脚和SCL引脚是开漏电路(参照资料)形式,因此,SDA和SCL总线都需要连接上拉电阻(参照资料),当总线空闲时,两条总线均为高电平。

  • 各器件的SDA和SCL信号线在总线上都是线与关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)

三、i2c协议层

协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。

1.i2c总线的位传输

数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 +数据改变:当SCL为低电平时,SDA才可以改变电平 +i2c位传输时序图 +在这里插入图片描述

2.i2c总线的开始和结束信号

开始信号:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 +结束信号:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。

3.i2c应答信号

  • 主机发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答ACK(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)
  • 从机接收不到数据或通信故障时,从机必须使SDA保持高电平,主机产生一个结束信号终止传输或者产生新的传输。

4.i2c总线的仲裁机制

  • SDA的仲裁也是建立在总线具有线与逻辑功能的原理上的。
  • 节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。
  • SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)
  • 当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是线与连接。

四、访问i2c总线设备

一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:

函数描述
rt_device_find()根据I2C 总线设备名称查找设备获取设备句柄
rt_i2c_transfer()传输数据

五、查找i2c总线设备

在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,

rt_device_t rt_device_find(const char* name);
+
参数描述
namei2c总线设备名称
返回
设备句柄查找到对应设备将返回相应的设备句柄
RT-NULL没有找到相应的设备对象

一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:

1
+2
+3
+4
+
#define AHT10_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称*/
+struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/
+/* 查找I2C总线设备, 获取I2C总线设备句柄*/
+i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
+

六、数据传输

获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:

1
+2
+3
+
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
+										struct rt_i2c_msg msgs[],
+										rt_uint32_t num);
+
参数描述
busi2c总线设备句柄
msgs[]待传输的消息数组指针
num消息数组的元素个数
返回-
--
消息数组的元素个数成功
错误码失败
  • 和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。
  • 参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 +!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。

I2C 消息数据结构原型如下:

1
+2
+3
+4
+5
+6
+7
+
struct rt_i2c_msg
+{
+rt_uint16_t addr; /* 从机地址*/
+rt_uint16_t flags; /* 读、写标志等*/
+rt_uint16_t len; /* 读写数据字节数*/
+rt_uint8_t *buf; /* 读写数据缓冲区指针 */
+}
+
  • 从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。
  • 标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 +!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。
1
+2
+3
+4
+5
+6
+
#define RT_I2C_WR 0x0000 /* 写标志*/
+#define RT_I2C_RD (1u << 0) /* 读标志*/
+#define RT_I2C_ADDR_10BIT (1u << 2) /* 10 位地址模式*/
+#define RT_I2C_NO_START (1u << 4) /* 无开始条件*/
+#define RT_I2C_IGNORE_NACK (1u << 5) /* 忽视NACK */
+#define RT_I2C_NO_READ_ACK (1u << 6) /* 读的时候不发送ACK */
+

使用示例如下所示:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
#define AHT10_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称*/
+#define AHT10_ADDR 0x38 /* 从机地址*/
+
+struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/
+
+/* 查找I2C总线设备, 获取I2C总线设备句柄*/
+i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
+
+/* 读传感器寄存器数据*/
+static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t
+*buf)
+{
+	struct rt_i2c_msg msgs;
+	msgs.addr = AHT10_ADDR; /* 从机地址*/
+	msgs.flags = RT_I2C_RD; /* 读标志*/
+	msgs.buf = buf; /* 读写数据缓冲区指针 */
+	msgs.len = len; /* 读写数据字节数*/
+	/* 调用I2C设备接口传输数据*/
+	if (rt_i2c_transfer(bus, &msgs, 1) == 1)
+	{
+		return RT_EOK;
+	}
+	else
+	{
+		return -RT_ERROR;
+	}
+}
+

七、I2C 总线设备使用示例

I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:

  1. 首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。
  2. 控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() +这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+
/*
+* 程序清单: 这是一个I2C 设备使用例程
+* 例程导出了i2c_aht10_sample 命令到控制终端
+* 命令调用格式: i2c_aht10_sample i2c1
+* 命令解释: 命令第二个参数是要使用的I2C总线设备名称 为空则使用默认的I2C总线设备
+* 程序功能: 通过I2C 设备读取温湿度传感器aht10 的温湿度数据并打印
+*/
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define AHT10_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称*/
+#define AHT10_ADDR 0x38 /* 从机地址*/
+#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/
+#define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/
+#define AHT10_GET_DATA 0xAC /* 获取数据命令*/
+
+static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄*/
+static rt_bool_t initialized = RT_FALSE; /* 传感器初始化状态*/
+
+/* 写传感器寄存器*/
+static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t*data)
+{
+	rt_uint8_t buf[3];
+	struct rt_i2c_msg msgs;
+	buf[0] = reg; //cmd
+	buf[1] = data[0];
+	buf[2] = data[1];
+	msgs.addr = AHT10_ADDR;
+	msgs.flags = RT_I2C_WR;
+	msgs.buf = buf;
+	msgs.len = 3;
+	
+	/* 调用I2C设备接口传输数据*/
+	if (rt_i2c_transfer(bus, &msgs, 1) == 1)
+	{
+		return RT_EOK;
+	}
+	else
+	{
+		return -RT_ERROR;
+	}
+}
+
+/* 读传感器寄存器数据*/
+static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t*buf)
+{
+	struct rt_i2c_msg msgs;
+	msgs.addr = AHT10_ADDR;
+	msgs.flags = RT_I2C_RD;
+	msgs.buf = buf;
+	msgs.len = len;
+
+	/* 调用I2C设备接口传输数据*/
+	if (rt_i2c_transfer(bus, &msgs, 1) == 1)
+	{
+		return RT_EOK;
+	}
+	else
+	{
+		return -RT_ERROR;
+	}
+}
+
+static void read_temp_humi(float *cur_temp, float *cur_humi)
+{
+	rt_uint8_t temp[6];
+	write_reg(i2c_bus, AHT10_GET_DATA, 0); /* 发送命令*/
+	rt_thread_mdelay(400);
+	read_regs(i2c_bus, 6, temp); /* 获取传感器数据*/
+	/* 湿度数据转换*/
+	*cur_humi = (temp[1] << 12 | temp[2] << 4 | (temp[3] & 0xf0) >> 4) * 100.0 / (1<< 20);
+	/* 温度数据转换*/
+	*cur_temp = ((temp[3] & 0xf) << 16 | temp[4] << 8 | temp[5]) * 200.0 / (1 << 20)- 50;
+}
+
+static void aht10_init(const char *name)
+{
+	rt_uint8_t temp[2] = {0, 0};
+	/* 查找I2C总线设备 获取I2C总线设备句柄*/
+	i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
+	if (i2c_bus == RT_NULL)
+	{
+		rt_kprintf("can't find %s device!\n", name);
+	}
+	else
+	{
+		write_reg(i2c_bus, AHT10_NORMAL_CMD, temp);
+		rt_thread_mdelay(400);
+		temp[0] = 0x08;
+		temp[1] = 0x00;
+		write_reg(i2c_bus, AHT10_CALIBRATION_CMD, temp);
+		rt_thread_mdelay(400);
+		initialized = RT_TRUE;
+	}
+}
+
+static void i2c_aht10_sample(int argc, char *argv[])
+{
+	float humidity, temperature;
+	char name[RT_NAME_MAX];
+	humidity = 0.0;
+	temperature = 0.0;
+	if (argc == 2)
+	{
+		rt_strncpy(name, argv[1], RT_NAME_MAX);
+	}
+	else
+	{
+		rt_strncpy(name, AHT10_I2C_BUS_NAME, RT_NAME_MAX);
+	}
+	if (!initialized)
+	{
+		/* 传感器初始化*/
+		aht10_init(name);
+	}
+	if (initialized)
+	{
+		/* 读取温湿度数据*/
+		read_temp_humi(&temperature, &humidity);
+		rt_kprintf("read aht10 sensor humidity : %d.%d %%\n", (int)humidity, (int)
+		(humidity * 10) % 10);
+		if( temperature >= 0 )
+		{
+			rt_kprintf("read aht10 sensor temperature: %d.%d°C\n", (int)temperature,
+			(int)(temperature * 10) % 10);
+		}
+		else
+		{
+			rt_kprintf("read aht10 sensor temperature: %d.%d°C\n", (int)temperature,
+			(int)(-temperature * 10) % 10);
+		}
+	}
+	else
+	{
+		rt_kprintf("initialize sensor failed!\n");
+	}
+}
+/* 导出到msh 命令列表中*/
+MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample);
+

学习资料参考:《嵌入式系统设计》RT-Thread

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 15, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/index.html" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/index.html" new file mode 100644 index 000000000..3f70ed90e --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\250-2.\345\206\205\346\240\270\345\256\236\346\210\230\347\257\207\347\272\277\347\250\213/index.html" @@ -0,0 +1,125 @@ +RT-Thread Studio使用 2.内核实战篇(线程) +
Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)

RT-Thread Studio使用 2.内核实战篇(线程)

在 RT-Thread 中,线程是实现任务的载体,它是 RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。

+
+

详细原理参考:【玩转RT-Thread】线程管理(详细原理)

一、线程创建

1、函数原型

1
+2
+3
+4
+5
+6
+7
+
// 线程创建
+rt_thread_t rt_thread_create(const char* name,
+							 void (*entry)(void* parameter),
+							 void* parameter,
+							 rt_uint32_t stack_size,
+							 rt_uint8_t priority,
+							 rt_uint32_t tick);
+

首先我们来看看线程创建函数返回值类型:

可以看到线程创建函数的返回值类型为:rt_thread_t,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。

2、线程定义

那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:

1
+
rt_thread_t th1_ptr = NULL
+

接下来就是我们给进程控制块传参了

3、线程创建判断

由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功

我们先来看下线程返回值(如下图)

如果成功创建的话,返回值是会返回我们所创建的线程对象的

如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
// 判断	
+if(th1_ptr == RT_NULL)
+    {
+        //错误信息打印
+        LOG_E("rt_thread_create create failed...\n");
+    	return -RT_ENOMEM; // 设定当线程th1_ptr创建失败后,返回一个空间不足的标志
+    }
+    
+    //打印debug调试信息
+    LOG_D("rt_thread_create create successed ...\n");
+

4、线程入口函数

我们在线程的入口处理函数写一个循环函数:

1
+2
+3
+4
+5
+6
+7
+8
+
void th_entry(void* parameter)
+{
+    while(1)
+    {
+        rt_kprintf("th_entry running ...\n");
+        rt_thread_mdelay(1000);
+    }
+}
+

注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源

  • 编译,串口观察

由于RTT studio有内置的串口终端,我们直接打开

终端输入list_thread可以查看所有的线程

5、总结

这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?

其实我们再看th_demo线程的状态可以看到是init,参考【玩转RT-Thread】线程管理(详细原理)

当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT

其实这句话就表明当线程处于初始化状态下是不参与系统调度的!

6、补充

线程错误码:

在这里插入图片描述


二、线程启动

函数原型

在主函数中加入命令,使线程进入就绪态:

1
+
rt_thread_startup(th1_ptr); 
+

但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为挂起态

解释:虽然我们调用rt_thread_startup函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了rt_thread_mdelay函数使其有一定时间的休眠,从而进入了挂起态`

三、初始化线程

rt_thread_init

1、函数声明

1
+2
+3
+4
+5
+6
+
// 模板函数
+rt_err_t rt_thread_init(struct rt_thread* thread,
+					    const char* name,
+						void (*entry)(void* parameter), void* parameter,
+						void* stack_start, rt_uint32_t stack_size,
+						rt_uint8_t priority, rt_uint32_t tick);
+

2、函数定义

1
+
ret = rt_thread_init(&th2,"th2_demo", th2_entry, NULL, th2_stack, sizeof(th2_stack), 19, 5);
+

此处我们需要定义一个ret整型变量用于rt_thread_init的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。

3、线程入口函数

代码如下:

1
+2
+3
+4
+5
+6
+7
+8
+
void th2_entry(void* parameter)
+{
+    for(i=0;i<10;i++)
+    {
+        rt_kprintf("th2_entry running ...\n");
+        rt_thread_mdelay(1000);
+    }
+}
+

4、判断创建状态

静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用rt_thread_startup函数使线程2进入就绪态,并执行线程处理函数。

1
+2
+3
+4
+5
+6
+7
+8
+
if(ret < 0)
+    {
+        LOG_E("rt2_thread_create create failed ...\n"); // 错误信息打印
+        return ret;
+    }
+    
+    LOG_D("rt_thread2_create create successes ...\n"); 
+    rt_thread_startup(&th2); // 创建成功后,我们开启线程,使其进入就绪态
+

这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启

5、实验结果

分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。

线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 14, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/index.html" "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/index.html" new file mode 100644 index 000000000..ecdcaf007 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadrt-thread-studio\344\275\277\347\224\2501\346\214\211\351\224\256\346\216\247\345\210\266\347\224\265\346\234\272\346\255\243\345\217\215\350\275\254\350\234\202\351\270\243\345\231\250/index.html" @@ -0,0 +1,280 @@ +RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器) +
Featured image of post RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)

RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)

RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。

+
+

一、初识RT-Thread

做世界级的 OS,让万物互联,信息畅通无阻。 +成为未来 AIoT 领域最为主流的操作系统平台。

1.简介

RT-Thread 是一个集实时操作系统(RTOS)内核、中间件组件和开发者社区于一体的技术平台,由熊谱翔先生带领并集合开源社区力量开发而成,RT-Thread 也是一个组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性物联网操作系统

2.前景

RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS

3.软件生态

RT-Thread 拥有良好的软件生态,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。

二、实验准备

  • 编程工具:RT-Thread studio
  • 开发板:潘多拉STM32L475

三、实验需求

  • 1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 +右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。
  • 2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。

四、操作流程

1.新建RT-Thread工程

在这里插入图片描述

2.RT-Thread Studio界面介绍

在这里插入图片描述

3.代码编写

在这里插入图片描述

4.烧录

在这里插入图片描述

5.串口监视

在这里插入图片描述

五、代码演示

1.头文件

#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+

2.宏定义

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
//按键初始化
+#define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --> KEY
+#define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --> KEY
+#define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --> KEY
+#define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP
+
+//电机初始化
+#define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A
+#define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B
+
+//蜂鸣器初始化
+#define PIN_BEEP GET_PIN(B,2)//PB2:BEEP
+
+enum
+{
+    MOTOR_STOP,
+    MOTOR_LEFT,
+    MOTOR_RIGHT
+};
+

3.void motor_ctrl(rt_uint8_t turn) //电机控制函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
void motor_ctrl(rt_uint8_t turn)
+{
+    if (turn == MOTOR_STOP)
+    {
+        rt_pin_write(PIN_MOTOR_A, PIN_LOW);
+        rt_pin_write(PIN_MOTOR_B, PIN_LOW);
+    }
+    else if (turn == MOTOR_LEFT)
+    {
+        rt_pin_write(PIN_MOTOR_A, PIN_LOW);
+        rt_pin_write(PIN_MOTOR_B, PIN_HIGH);
+    }
+    else if (turn == MOTOR_RIGHT)
+    {
+        rt_pin_write(PIN_MOTOR_A, PIN_HIGH);
+        rt_pin_write(PIN_MOTOR_B, PIN_LOW);
+    }
+    else
+    {
+        rt_kprintf("err parameter ! Please enter 0-2.");
+    }
+}
+

4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
void beep_ctrl(rt_uint8_t on)
+{
+    if (on)
+    {
+        rt_pin_write(PIN_BEEP, PIN_HIGH);
+    }
+    else
+    {
+        rt_pin_write(PIN_BEEP, PIN_LOW);
+    }
+}
+

5.void irq_callback(void *args) // 中断回调函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
void irq_callback(void *args)
+{
+    rt_uint32_t sign = (rt_uint32_t)args;
+    switch (sign)
+    {
+        case PIN_KEY0:
+        motor_ctrl(MOTOR_LEFT);
+        rt_kprintf("KEY0 interrupt. motor turn left.");
+        break;
+        case PIN_KEY1:
+        motor_ctrl(MOTOR_RIGHT);
+        rt_kprintf("KEY1 interrupt. motor turn right.");
+        break;
+        case PIN_KEY2:
+        motor_ctrl(MOTOR_STOP);
+        rt_kprintf("KEY2 interrupt. motor stop.");
+        break;
+        default:
+        rt_kprintf("error sign= %d !", sign);
+        break;
+    }
+}
+

5.主函数

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
int main(void)
+{
+    unsigned int count = 1;
+
+    /* 设置按键引脚为输入模式*/
+    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP);
+    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP);
+    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP);
+    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN);
+
+    /* 设置电机控制引脚为输入模式*/
+    rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT);
+    rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT);
+
+    /* 设置蜂鸣器引脚为输出模式*/
+    rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT);
+
+    /* 设置按键中断模式与中断回调函数*/
+    rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0
+    );
+    rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1
+    );
+    rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2
+    );
+
+    /* 使能中断*/
+    rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE);
+    rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE);
+    rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE);
+    while (count > 0)
+    {
+        if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
+        {
+            rt_thread_mdelay(50);
+            if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
+            {
+                rt_kprintf("WK_UP pressed. beep on.");
+                beep_ctrl(1);
+            }
+        }
+        else
+        {
+            beep_ctrl(0);
+        }
+        rt_thread_mdelay(10);
+        count++;
+    }
+
+    return 0;
+}
+

六、原理讲解

通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 +1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 +2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。

按键功能
KEY0电机左转
KEY1电机右转
KEY2电机停止
WK_UP蜂鸣器响
+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 15, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef.jpg" new file mode 100644 index 000000000..c80f75200 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef_hub6a66fbbe5f509b396b5c62bec10766b_210091_250x150_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef_hub6a66fbbe5f509b396b5c62bec10766b_210091_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9cdadf8a1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.1aa01bcbac2a20a76c18432688d7e6ef_hub6a66fbbe5f509b396b5c62bec10766b_210091_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.jpg" new file mode 100644 index 000000000..c80f75200 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9c4cfaa87 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..baf7ae953 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..cbbab291c Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/index.html" "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/index.html" new file mode 100644 index 000000000..a01ea822d --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadrt-thread\345\206\205\346\240\270\345\256\217\345\256\232\344\271\211\350\257\246\350\247\243rtdef.h/index.html" @@ -0,0 +1,419 @@ +RT-Thread内核宏定义详解(rtdef.h) +
Featured image of post RT-Thread内核宏定义详解(rtdef.h)

RT-Thread内核宏定义详解(rtdef.h)

RT-Thread是一款轻量级的实时操作系统,它在嵌入式系统领域得到了广泛应用。其中,rtdef.h 头文件定义了RT-Thread操作系统中很多重要的宏定义,这些宏定义提供了对操作系统内部数据结构和常用函数的封装和定义。通过了解和掌握这些宏定义,可以更方便地编写和调试 RT-Thread 应用程序,从而提高程序的可靠性和健壮性。本文将详细介绍 rtdef.h 头文件中部分宏定义的作用、用法和注意事项,帮助读者深入理解 RT-Thread 内核,在开发嵌入式应用时更加得心应手。

+
+

1.RT-Thread版本信息

1
+2
+3
+4
+5
+6
+7
+
/* RT-Thread version information */
+#define RT_VERSION                      4               /**< major version number */
+#define RT_SUBVERSION                   1               /**< minor version number */
+#define RT_REVISION                     1               /**< revise version number */
+
+/* RT-Thread version */
+#define RTTHREAD_VERSION                RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION)
+

使用方法:可用于bsp指定RT-Thread版本

例如:

1
+2
+3
+
#if (RTTHREAD_VERSION >= RT_VERSION_CHECK(4, 1, 0) */
+#define RT_VERSION_CHECK(major, minor, revise)          ((major * 10000) + \
+                                                         (minor * 100) + revise)
+

2.RT-Thrad基础数据类型定义

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
/* RT-Thread basic data type definitions */
+#ifndef RT_USING_ARCH_DATA_TYPE	/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */
+#ifdef RT_USING_LIBC		   /* 用于控制是否使用标准C库函数 */
+typedef int8_t                          rt_int8_t;      /**<  8bit integer type */
+typedef int16_t                         rt_int16_t;     /**< 16bit integer type */
+typedef int32_t                         rt_int32_t;     /**< 32bit integer type */
+typedef uint8_t                         rt_uint8_t;     /**<  8bit unsigned integer type */
+typedef uint16_t                        rt_uint16_t;    /**< 16bit unsigned integer type */
+typedef uint32_t                        rt_uint32_t;    /**< 32bit unsigned integer type */
+typedef int64_t                         rt_int64_t;     /**< 64bit integer type */
+typedef uint64_t                        rt_uint64_t;    /**< 64bit unsigned integer type */
+typedef size_t                          rt_size_t;      /**< Type for size number */
+
+#else
+typedef signed   char                   rt_int8_t;      /**<  8bit integer type */
+typedef signed   short                  rt_int16_t;     /**< 16bit integer type */
+typedef signed   int                    rt_int32_t;     /**< 32bit integer type */
+typedef unsigned char                   rt_uint8_t;     /**<  8bit unsigned integer type */
+typedef unsigned short                  rt_uint16_t;    /**< 16bit unsigned integer type */
+typedef unsigned int                    rt_uint32_t;    /**< 32bit unsigned integer type */
+
+#ifdef ARCH_CPU_64BIT	/* 判断当前程序运行的CPU架构是否为64位 */
+typedef signed long                     rt_int64_t;     /**< 64bit integer type */
+typedef unsigned long                   rt_uint64_t;    /**< 64bit unsigned integer type */
+typedef unsigned long                   rt_size_t;      /**< Type for size number */
+#else
+typedef signed long long                rt_int64_t;     /**< 64bit integer type */
+typedef unsigned long long              rt_uint64_t;    /**< 64bit unsigned integer type */
+typedef unsigned int                    rt_size_t;      /**< Type for size number */
+#endif /* ARCH_CPU_64BIT */
+#endif /* RT_USING_LIBC */
+#endif /* RT_USING_ARCH_DATA_TYPE */
+
+typedef int                             rt_bool_t;      /**< boolean type */
+typedef long                            rt_base_t;      /**< Nbit CPU related date type */
+typedef unsigned long                   rt_ubase_t;     /**< Nbit unsigned CPU related data type */
+
+typedef rt_base_t                       rt_err_t;       /**< Type for error number */
+typedef rt_uint32_t                     rt_time_t;      /**< Type for time stamp */
+typedef rt_uint32_t                     rt_tick_t;      /**< Type for tick count */
+typedef rt_base_t                       rt_flag_t;      /**< Type for flags */
+typedef rt_ubase_t                      rt_dev_t;       /**< Type for device */
+typedef rt_base_t                       rt_off_t;       /**< Type for offset */
+
+/* boolean type definitions */
+#define RT_TRUE                         1               /**< boolean true  */
+#define RT_FALSE                        0               /**< boolean fails */
+
+/* null pointer definition */
+#define RT_NULL                         0
+
  • rt_base_t:为了使代码可以在不同的CPU上移植并保持向后兼容性long类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用rt_base_t代替long可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)

  • rt_err_t:代表错误码的数据类型,这里使用了之前定义的rt_base_t作为它的别名。

  • rt_time_t:代表时间戳的数据类型,这里使用了rt_uint32_t作为它的别名。rt_uint32_t是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。

  • rt_tick_t:代表系统时钟节拍计数的数据类型,这里也使用了rt_uint32_t作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对rt_tick_t进行递增操作,从而实现对时间的计数。

  • rt_flag_t:代表标志位的数据类型,这里使用了之前定义的rt_base_t作为它的别名。

  • rt_dev_t:代表设备号的数据类型,这里使用了rt_ubase_t作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。

  • rt_off_t:代表偏移量的数据类型,这里也使用了之前定义的rt_base_t作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。

3.RT-Thread基本数据类型的范围

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+
/* maximum value of base type */
+#ifdef RT_USING_LIBC
+#define RT_UINT8_MAX                    UINT8_MAX       /**< Maximum number of UINT8 */
+#define RT_UINT16_MAX                   UINT16_MAX      /**< Maximum number of UINT16 */
+#define RT_UINT32_MAX                   UINT32_MAX      /**< Maximum number of UINT32 */
+#else
+#define RT_UINT8_MAX                    0xff            /**< Maximum number of UINT8 */
+#define RT_UINT16_MAX                   0xffff          /**< Maximum number of UINT16 */
+#define RT_UINT32_MAX                   0xffffffff      /**< Maximum number of UINT32 */
+#endif /* RT_USING_LIBC */
+

附:此处的UINT8_MAXUINT16_MAXUINT32_MAX为编译器预定的宏定义

4.RT-Thread系统滴答时钟最大计数值

1
+
#define RT_TICK_MAX                     RT_UINT32_MAX   /**< Maximum number of tick */
+

5.RT-Thread IPC数据类型范围

1
+2
+3
+4
+5
+6
+
/* maximum value of ipc type */
+#define RT_SEM_VALUE_MAX                RT_UINT16_MAX   /**< Maximum number of semaphore .value */
+#define RT_MUTEX_VALUE_MAX              RT_UINT16_MAX   /**< Maximum number of mutex .value */
+#define RT_MUTEX_HOLD_MAX               RT_UINT8_MAX    /**< Maximum number of mutex .hold */
+#define RT_MB_ENTRY_MAX                 RT_UINT16_MAX   /**< Maximum number of mailbox .entry */
+#define RT_MQ_ENTRY_MAX                 RT_UINT16_MAX   /**< Maximum number of message queue .entry */
+

6.RT-Thread避免未使用变量警告

1
+
#define RT_UNUSED(x)                   ((void)x)
+

**该宏定义表示将变量x强制转换为void类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **

下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。

该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。

在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。

这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
#include <stdlib.h>
+
+int cmp(const void *a, const void *b)
+{
+    /* sort code */
+}
+
+int main()
+{
+    int arr[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
+    qsort(arr, 10, sizeof(int), cmp);  // 必须传递一个void*类型参数
+    return 0;
+}
+
+int cmp(const void *a, const void *b)
+{
+    RT_UNUSED(a);  // 标记参数未使用
+    RT_UNUSED(b);  // 标记参数未使用
+    return 0;
+}
+

这样就可以避免编译器报“未使用变量a/b”的警告了。

7.编译器相关定义

1
+2
+3
+4
+5
+6
+7
+
/* Compiler Related Definitions */
+#if defined(__ARMCC_VERSION)           /* ARM Compiler */
+#define RT_SECTION(x)               __attribute__((section(x)))
+#define RT_USED                     __attribute__((used))
+#define ALIGN(n)                    __attribute__((aligned(n)))
+#define RT_WEAK                     __attribute__((weak))
+#define rt_inline                   static __inline
+
  • RT_SECTION(x):表示将所修饰的数据/函数放置在指定的section中,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。
  • RT_USED:表示告诉编译器保留所修饰的数据/函数,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。
  • ALIGN(n):表示将所修饰的数据/函数按照n字节对齐,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。
  • RT_WEAK:表示将所修饰的数据/函数标记为弱引用,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。
  • rt_inline:表示将所修饰的函数定义为静态内联函数,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。

8.编译器相关定义

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+
/* Compiler Related Definitions */
+#if defined(__ARMCC_VERSION)           /* ARM Compiler */
+#define RT_SECTION(x)               __attribute__((section(x)))
+#define RT_USED                     __attribute__((used))
+#define ALIGN(n)                    __attribute__((aligned(n)))
+#define RT_WEAK                     __attribute__((weak))
+#define rt_inline                   static __inline
+
+/* module compiling */
+#ifdef RT_USING_MODULE
+#define RTT_API                     __declspec(dllimport)
+#else
+#define RTT_API                     __declspec(dllexport)
+#endif /* RT_USING_MODULE */
+
+#elif defined (__IAR_SYSTEMS_ICC__)     /* for IAR Compiler */
+#define RT_SECTION(x)               @ x
+#define RT_USED                     __root
+#define PRAGMA(x)                   _Pragma(#x)
+#define ALIGN(n)                    PRAGMA(data_alignment=n)
+#define RT_WEAK                     __weak
+#define rt_inline                   static inline
+#define RTT_API
+#elif defined (__GNUC__)                /* GNU GCC Compiler */
+
+#ifndef RT_USING_LIBC
+/* the version of GNU GCC must be greater than 4.x */
+typedef __builtin_va_list           __gnuc_va_list;
+typedef __gnuc_va_list              va_list;
+#define va_start(v,l)               __builtin_va_start(v,l)
+#define va_end(v)                   __builtin_va_end(v)
+#define va_arg(v,l)                 __builtin_va_arg(v,l)
+#endif /* RT_USING_LIBC */
+
+#define RT_SECTION(x)               __attribute__((section(x)))
+#define RT_USED                     __attribute__((used))
+#define ALIGN(n)                    __attribute__((aligned(n)))
+#define RT_WEAK                     __attribute__((weak))
+#define rt_inline                   static __inline
+#define RTT_API
+
+#elif defined (__ADSPBLACKFIN__)        /* for VisualDSP++ Compiler */
+#define RT_SECTION(x)               __attribute__((section(x)))
+#define RT_USED                     __attribute__((used))
+#define ALIGN(n)                    __attribute__((aligned(n)))
+#define RT_WEAK                     __attribute__((weak))
+#define rt_inline                   static inline
+#define RTT_API
+
+#elif defined (_MSC_VER)
+#define RT_SECTION(x)
+#define RT_USED
+#define ALIGN(n)                    __declspec(align(n))
+#define RT_WEAK
+#define rt_inline                   static __inline
+#define RTT_API
+
+#elif defined (__TI_COMPILER_VERSION__)
+/* The way that TI compiler set section is different from other(at least
+    * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more
+    * details. */
+#define RT_SECTION(x)
+#define RT_USED
+#define PRAGMA(x)                   _Pragma(#x)
+#define ALIGN(n)
+#define RT_WEAK
+#define rt_inline                   static inline
+#define RTT_API
+
+#elif defined (__TASKING__)
+#define RT_SECTION(x)               __attribute__((section(x)))
+#define RT_USED                     __attribute__((used, protect))
+#define PRAGMA(x)                   _Pragma(#x)
+#define ALIGN(n)                    __attribute__((__align(n)))
+#define RT_WEAK                     __attribute__((weak))
+#define rt_inline                   static inline
+#define RTT_API
+#else
+    #error not supported tool chain
+#endif /* __ARMCC_VERSION */
+
  1. typedef __builtin_va_list __gnuc_va_list: 定义了一个新类型__gnuc_va_list,并使用 __builtin_va_list 进行初始化。__builtin_va_list 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 __builtin_va_list 类型来实现可变参数列表。
  2. typedef __gnuc_va_list va_list: 定义了一个名为va_list的新类型,并将其重命名为__gnuc_va_list
  3. #define va_start(v,l) __builtin_va_start(v,l): 将 va_start() 重命名为 __builtin_va_start(),从而能够使用 GCC 内建的函数 __builtin_va_start() 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。
  4. #define va_end(v) __builtin_va_end(v): 将 va_end() 重命名为 __builtin_va_end(),从而能够使用 GCC 内建的函数 __builtin_va_end() 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。
  5. #define va_arg(v,l) __builtin_va_arg(v,l): 将 va_arg() 重命名为 __builtin_va_arg(),并使用 GCC 内建的函数 __builtin_va_arg() 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。
  6. #define PRAGMA(x) _Pragma(#x):将参数x转化为字符串并使用_Pragma()将其作为编译指令执行。_Pragma是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而#pragma则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。

9.RT-Thread错误码定义

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
/* RT-Thread error code definitions */
+#define RT_EOK                          0               /**< There is no error */
+#define RT_ERROR                        1               /**< A generic error happens */
+#define RT_ETIMEOUT                     2               /**< Timed out */
+#define RT_EFULL                        3               /**< The resource is full */
+#define RT_EEMPTY                       4               /**< The resource is empty */
+#define RT_ENOMEM                       5               /**< No memory */
+#define RT_ENOSYS                       6               /**< No system */
+#define RT_EBUSY                        7               /**< Busy */
+#define RT_EIO                          8               /**< IO error */
+#define RT_EINTR                        9               /**< Interrupted system call */
+#define RT_EINVAL                       10              /**< Invalid argument */
+
  • RT_EOK:表示没有错误。
  • RT_ERROR:表示发生了一般性的错误。
  • RT_ETIMEOUT:表示超时错误。
  • RT_EFULL:表示资源已满。
  • RT_EEMPTY:表示资源为空。
  • RT_ENOMEM:表示内存不足。
  • RT_ENOSYS:表示没有该系统。
  • RT_EBUSY:表示忙碌。
  • RT_EIO:表示输入/输出错误。
  • RT_EINTR:表示中断的系统调用。
  • RT_EINVAL:表示无效的参数。
+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 09, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29.jpg" new file mode 100644 index 000000000..b2f236eb1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_250x150_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c1abb8b74 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.08eeaccb6311af818ce14414d996ba29_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.jpg" new file mode 100644 index 000000000..b2f236eb1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..b6b25a9bf Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..29ba5c0de Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..952553f36 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/index.html" "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/index.html" new file mode 100644 index 000000000..f2a7c6ab0 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-threadrt-thread\347\275\221\347\273\234\346\241\206\346\236\266bsd\347\275\221\347\273\234\346\216\245\345\217\243sal\345\245\227\346\216\245\345\255\227\346\212\275\350\261\241\345\261\202/index.html" @@ -0,0 +1,563 @@ +RT-Thread网络框架:BSD网络接口&SAL套接字抽象层 +
Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层

RT-Thread网络框架:BSD网络接口&SAL套接字抽象层

RT-Thread是一款轻量级的实时操作系统,它在嵌入式系统领域得到了广泛应用。

+
+

RT-Thread网络框架:BSD网络接口&SAL套接字抽象层


基础知识

1.TCP与UDP的区别

TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。

OSI七层模型和TCP/IP四层模型详解请看此处

区别:

  • TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。
  • TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。
  • TCP面向字节流;UDP面向报文。
  • TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。
  • TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。
  • TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。

2.TCP编程 服务端配置过程

  • socket():创建一个socket
  • setsockopt():设置socket属性
  • bind():绑定IP地址、端口等信息到socket类上
  • listen():开启监听
  • accept():接收来自客户端的连接
  • 收发数据:send()、recv()、read()、write()
  • 关闭网络连接
  • 关闭监听

3.TCP编程 客户端配置过程

  • socket():创建一个socket
  • setsockopt():设置socket属性,可选
  • bind():绑定IP地址、端口等信息到socket上
  • recvfrom():循环接收数据
  • 关闭网络连接

4.UDP编程 客户端配置过程

  • socket():创建一个socket
  • setsockopt():设置socket属性,可选
  • bind():绑定IP地址、端口等信息到socket上
  • 设置对方的IP地址和端口等属性
  • sendto():发送数据
  • 关闭网络连接

SAL套接字抽象层

SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。

1.SAL组件主要功能特点:

  • 抽象、统一多种网络协议栈接口
  • 提供Socket层面的TLS加密传输特性
  • 支持标准 BSD Socket API
  • 统一的FD管理,便于使用read/write poll/select来操作网络功能

2.SAL网络框架

image-20230411131524312

  • 应用层:提供一套标准BSD Socket API1。如socket、connect等函数,用于系统中大部分网络开发应用。
  • SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。
  • netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。
  • 协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的轻型TCP/IP协议栈lwip以及RT-Thread自主研发的AT Socket网络功能实现等。

3.工作原理

SAL组件工作原理的介绍主要分为如下两部分:

  • 多协议栈接入与接口函数统一抽象功能
  • SAL TLS加密传输功能

4.多协议接入与接口函数统一抽象功能

由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。

目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)2

1
+
int socket(int domain, int type, int protocol);
+

为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:主协议簇类型和次协议簇类型,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。

具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。

目前系统支持协议簇类型如下:

1
+2
+3
+
LWIP协议栈family = AF_INETsec_family = AF_INET
+AT Socket协议栈family = AF_ATsec_family = AF_INET
+WIZnet硬件 TCP/IP协议栈family = AF_WIZ
+

SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:

  • connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;
  • sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;
  • lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
/* SAL 组件为应用层提供的标准 BSD Socket API */
+int connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+    /* 获取 SAL 套接字描述符 */
+    int socket = dfs_net_getsocket(s);
+
+    /* 通过 SAL 套接字描述符执行 sal_connect 函数 */
+    return sal_connect(socket, name, namelen);
+}
+
+/* SAL 组件抽象函数接口实现 */
+int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
+{
+    struct sal_socket *sock;
+    struct sal_proto_family *pf;
+    int ret;
+
+    /* 检查 SAL socket 结构体是否正常 */
+    SAL_SOCKET_OBJ_GET(sock, socket);
+
+    /* 检查当前 socket 网络连接状态是否正常  */
+    SAL_NETDEV_IS_COMMONICABLE(sock->netdev);
+    /* 检查当前 socket 对应的底层 operation 函数是否正常  */
+    SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, connect);
+
+    /* 执行底层注册的 connect operation 函数 */
+    ret = pf->skt_ops->connect((int) sock->user_data, name, namelen);
+#ifdef SAL_USING_TLS
+    if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect))
+    {
+        if (proto_tls->ops->connect(sock->user_data_tls) < 0)
+        {
+            return -1;
+        }
+        return ret;
+    }
+#endif
+    return ret;
+}
+
+/* lwIP 协议栈函数底层 connect 函数实现 */
+int lwip_connect(int socket, const struct sockaddr *name, socklen_t namelen)
+{
+    ...
+}
+

5.SAL TLS加密传输功能

在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。

TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。3

对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。

使用流程:

  • 配置开启任意网络协议栈支持(如LWIP协议栈)
  • 配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)
  • 配置开启SAL_TLS功能支持

配置完成后,需要在socket创建时传入的potocol类型是使用PROTOCOL_TLS或者PROTOCOL_DTLS,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。

示例如下,参考RT-Threda文档中心:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+
#include <stdio.h>
+#include <string.h>
+
+#include <rtthread.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+/* RT-Thread 官网,支持 TLS 功能 */
+#define SAL_TLS_HOST    "www.rt-thread.org"
+#define SAL_TLS_PORT    443
+#define SAL_TLS_BUFSZ   1024
+
+static const char *send_data = "GET /download/rt-thread.txt HTTP/1.1\r\n"
+    "Host: www.rt-thread.org\r\n"
+    "User-Agent: rtthread/4.0.1 rtt\r\n\r\n";
+
+void sal_tls_test(void)
+{
+    int ret, i;
+    char *recv_data;
+    struct hostent *host;
+    int sock = -1, bytes_received;
+    struct sockaddr_in server_addr;
+
+    /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
+    host = gethostbyname(SAL_TLS_HOST);
+
+    recv_data = rt_calloc(1, SAL_TLS_BUFSZ);
+    if (recv_data == RT_NULL)
+    {
+        rt_kprintf("No memory\n");
+        return;
+    }
+
+    /* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */
+    if ((sock = socket(AF_INET, SOCK_STREAM, PROTOCOL_TLS)) < 0)
+    {
+        rt_kprintf("Socket error\n");
+        goto __exit;
+    }
+
+    /* 初始化预连接的服务端地址 */
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = htons(SAL_TLS_PORT);
+    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
+    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
+
+    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
+    {
+        rt_kprintf("Connect fail!\n");
+        goto __exit;
+    }
+
+    /* 发送数据到 socket 连接 */
+    ret = send(sock, send_data, strlen(send_data), 0);
+    if (ret <= 0)
+    {
+        rt_kprintf("send error,close the socket.\n");
+        goto __exit;
+    }
+
+    /* 接收并打印响应的数据,使用加密数据传输 */
+    bytes_received = recv(sock, recv_data, SAL_TLS_BUFSZ  - 1, 0);
+    if (bytes_received <= 0)
+    {
+        rt_kprintf("received error,close the socket.\n");
+        goto __exit;
+    }
+
+    rt_kprintf("recv data:\n");
+    for (i = 0; i < bytes_received; i++)
+    {
+        rt_kprintf("%c", recv_data[i]);
+    }
+
+__exit:
+    if (recv_data)
+        rt_free(recv_data);
+
+    if (sock >= 0)
+        closesocket(sock);
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+MSH_CMD_EXPORT(sal_tls_test, SAL TLS function test);
+#endif /* FINSH_USING_MSH */
+

BSD Socket API

1.创建套接字(socket)

为通信创建一个端点并返回一个文件描述符

1
+
int socket(int domain, int type, int protocol);
+
  • domain:确定协议簇
  • type:数据类型
  • protocol:协议
1
+2
+3
+
# domain / 协议族类型
+AF_INET		#  IPv4 协议族
+AF_INET6	#  IPv6 协议族
+
1
+2
+3
+4
+5
+
# type / 协议类型
+/* Socket protocol types (1:TCP/2:UDP/3:RAW) */
+#define SOCK_STREAM     1
+#define SOCK_DGRAM      2
+#define SOCK_RAW        3
+

2.绑定套接字(bind)

当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。

1
+
int bind(int s, const struct sockaddr *name, socklen_t namelen);
+
  • s:代表socket的文件描述符
  • name:指向sockaddr结构体的指针,代表要绑定的地址
  • namelen:是sockaddr结构体的大小

附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。

来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
#include <rtthread.h>
+#include <arpa/inet.h>
+#include <netdev.h>
+
+#define SERVER_HOST   "192.168.1.123"
+#define SERVER_PORT   1234
+
+static int bing_test(int argc, char **argv)
+{
+    struct sockaddr_in client_addr;
+    struct sockaddr_in server_addr;
+    struct netdev *netdev = RT_NULL;
+    int sockfd = -1;
+
+    if (argc != 2)
+    {
+        rt_kprintf("bind_test [netdev_name]  --bind network interface device by name.\n");
+        return -RT_ERROR;
+    }
+
+    /* 通过名称获取 netdev 网卡对象 */
+    netdev = netdev_get_by_name(argv[1]);
+    if (netdev == RT_NULL)
+    {
+        rt_kprintf("get network interface device(%s) failed.\n", argv[1]);
+        return -RT_ERROR;
+    }
+
+    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    {
+        rt_kprintf("Socket create failed.\n");
+        return -RT_ERROR;
+    }
+
+    /* 初始化需要绑定的客户端地址 */
+    client_addr.sin_family = AF_INET;
+    client_addr.sin_port = htons(8080);
+    /* 获取网卡对象中 IP 地址信息 */
+    client_addr.sin_addr.s_addr = netdev->ip_addr.addr;
+    rt_memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
+
+    if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) < 0)
+    {
+        rt_kprintf("socket bind failed.\n");
+        closesocket(sockfd);
+        return -RT_ERROR;
+    }
+    rt_kprintf("socket bind network interface device(%s) success!\n", netdev->name);
+
+    /* 初始化预连接的服务端地址 */
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = htons(SERVER_PORT);
+    server_addr.sin_addr.s_addr = inet_addr(SERVER_HOST);
+    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
+
+    /* 连接到服务端 */
+    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
+    {
+        rt_kprintf("socket connect failed!\n");
+        closesocket(sockfd);
+        return -RT_ERROR;
+    }
+    else
+    {
+        rt_kprintf("socket connect success!\n");
+    }
+
+    /* 关闭连接 */
+    closesocket(sockfd);
+    return RT_EOK;
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+MSH_CMD_EXPORT(bing_test, bind network interface device test);
+#endif /* FINSH_USING_MSH */
+

3.监听套接字(listen)

当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。

1
+
int listen(int s, int backlog);
+
  • sockfd:代表socket的文件描述符
  • backlog:一个整数,表示一次能够等待的最大连接数目。

4.接收连接(accept)

当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。

1
+
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+
  • s:监听的套接字描述符
  • addr:指向sockaddr结构体的指针,服务器地址信息
  • addrlen:sockaddr结构体的大小

5.建立连接(connect)

该函数用于建立与指定 socket 的连接。

1
+
int connect(int s, const struct sockaddr *name, socklen_t namelen);
+
  • s:套接字描述符
  • name:服务器地址信息
  • namelen:服务器地址结构体长度

6.TCP数据发送(send)

该函数常用于 TCP 连接发送数据。

1
+
int send(int s, const void *dataptr, size_t size, int flags);
+
  • s:套接字描述符
  • dataptr:发送的数据指针
  • size:发送的数据长度
  • flags:标志,一般为 0

7.TCP数据接收(recv)

该函数用于TCP连接接收数据。

1
+
int recv(int s, void *mem, size_t len, int flags);
+
  • s:套接字描述符
  • mem:接收的数据指针
  • len:接收的数据长度
  • flags:标志,一般为0

8.UDP数据发送(sendto)

该函数用于UDP连接发送数据。

1
+
int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
+
  • S:套接字描述符
  • dataptr:发送的数据指针
  • size:发送的数据长度
  • flags:标志,一般为0
  • to:目标结构体指针
  • tolen:目标地址结构体长度

9.UDP数据接收(recfrom)

该函数用于UDP连接发送数据。

1
+
int recvfrom(int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
+
  • S:套接字描述符
  • mem:接收的数据指针
  • len:接收的数据长度
  • flags:标志,一般为0
  • from:接收地址结构体指针
  • fromlen:接收地址结构体长度

SAL网络协议栈接入方式

网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
/* network interface socket opreations */
+struct sal_socket_ops
+{
+    int (*socket)     (int domain, int type, int protocol);
+    int (*closesocket)(int s);
+    int (*bind)       (int s, const struct sockaddr *name, socklen_t namelen);
+    int (*listen)     (int s, int backlog);
+    int (*connect)    (int s, const struct sockaddr *name, socklen_t namelen);
+    int (*accept)     (int s, struct sockaddr *addr, socklen_t *addrlen);
+    int (*sendto)     (int s, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
+    int (*recvfrom)   (int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
+    int (*getsockopt) (int s, int level, int optname, void *optval, socklen_t *optlen);
+    int (*setsockopt) (int s, int level, int optname, const void *optval, socklen_t optlen);
+    int (*shutdown)   (int s, int how);
+    int (*getpeername)(int s, struct sockaddr *name, socklen_t *namelen);
+    int (*getsockname)(int s, struct sockaddr *name, socklen_t *namelen);
+    int (*ioctlsocket)(int s, long cmd, void *arg);
+#ifdef SAL_USING_POSIX
+    int (*poll)       (struct dfs_fd *file, struct rt_pollreq *req);
+#endif
+};
+
+/* sal network database name resolving */
+struct sal_netdb_ops
+{
+    struct hostent* (*gethostbyname)  (const char *name);
+    int             (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
+    int             (*getaddrinfo)    (const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
+    void            (*freeaddrinfo)   (struct addrinfo *ai);
+};
+
+/* 协议簇结构体定义 */
+struct sal_proto_family
+{
+    int family;                                  /* primary protocol families type */
+    int sec_family;                              /* secondary protocol families type */
+    const struct sal_socket_ops *skt_ops;        /* socket opreations */
+    const struct sal_netdb_ops *netdb_ops;       /* network database opreations */
+};
+
  • family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。
  • sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。
  • skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。
  • netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。

附录


  1. 伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的抽象标准。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。 ↩︎

  2. WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将TCP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。 ↩︎

  3. 在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。 ↩︎

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover.jpg" "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/index.html" "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/index.html" new file mode 100644 index 000000000..0697fde32 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-thread\346\227\266\351\222\237\347\256\241\347\220\206\345\216\237\347\220\206-\345\256\236\346\210\230/index.html" @@ -0,0 +1,268 @@ +时钟管理(原理+实战) +
Featured image of post 时钟管理(原理+实战)

时钟管理(原理+实战)

操作系统需要通过时间来规范其任务的执行,操作系统中最小的时间单位是时钟节拍 (OS Tick)。

+
+

一、时钟节拍

任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。

RT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!

rtconfig.h配置文件中定义:

  • 频率是1000HZ周期是1/1000 s

  • 所以节拍是1ms

  • #define RT_ TiCK PER_ SECOND 1000

1、void SysTick_Handler()

在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行void SysTick_Handler(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)

可以发现在void SysTick_Handler()这个函数中,首先会执行中断入口函数,然后void rt_tick_increasert_tick(系统滴答时钟,初值为0,静态全局变量)进行自加操作,会记录从启动到现在的时钟节拍数

2、void rt_tick_increase()

也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断

3、rt_tick_get(void);

名称:获取系统统计函数

功能:返回当前操作系统的时钟数

返回值:返回当前时钟数

二、定时器管理

1、概念

定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有硬件定时器软件定时器之分:

1)硬件定时器是芯片本身提供的定时功能。一般是由外部晶振(HSE)提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式

2)软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。

RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时数值必须是 OS Tick 的整数倍,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。

2、RT-Thread定时器介绍

RT-Thread 的定时器提供两类定时器机制:

第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 +第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远持续执行下去。

另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 HARD_TIMER 模式(硬件定时器模式)与 SOFT_TIMER 模式(软件定时器模式),如下图。

1)HARD_TIMER 模式:中断上下文

HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数RT_TIMER_FLAG_HARD_TIMER来指定。

在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。

2)SOFT_TIMER 模式:线程上下文

SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。

该模式被启用后,系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

3、定时器源码分析

1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数

2)rt_system_timer_init(硬件定时器初始化)

1
+2
+3
+4
+5
+6
+7
+8
+9
+
void rt_system_timer_init(void)
+{
+    int i;// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入
+    
+    for (i = 0; i < sizeof(rt_timer_list) / sizeof(rt_timer_list[0]); i++)
+    {
+        rt_list_init(rt_timer_list + i);
+    }
+}
+

3)rt_system_timer_thread_init(软件定时器初始化)

4、定时器工作机制

下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的全局变量

(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);

(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到 rt_timer_list 链表中。

如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。

而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),50 个 tick 以后,rt_tick 从 20 增长到 70,与 Timer1 的 timeout 值相等,这时会触发与 Timer1 定时器相关联的超时函数,同时将 Timer1 从 rt_timer_list 链表上删除

同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。

如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 timeout=rt_tick+300=330, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:

5、定时器相关接口

1)动态创建定时器

动态创建声明:

1
+2
+3
+4
+5
+
rt_timer_t rt_timer_create(const char *name,
+                           void (*timeout)(void *parameter),
+                           void       *parameter,
+                           rt_tick_t   time,
+                           rt_uint8_t  flag);
+

详细函数定义:

查看flag定义:

1
+2
+3
+4
+5
+
#define RT_TIMER_FLAG_ONE_SHOT          0x0             // 单次触发
+#define RT_TIMER_FLAG_PERIODIC          0x2             // 周期性触发
+
+#define RT_TIMER_FLAG_HARD_TIMER        0x0             // 硬件定时器模式
+#define RT_TIMER_FLAG_SOFT_TIMER        0x4				// 软件定时器模式
+

同时这里我们注意到rt_timer_create这个函数的返回值是rt_timer_t,通过查找定义可以发现该类型是通过typedef重命名的

也就是说struct rt_timer <=>*rt_timer_t

1
+
typedef struct rt_timer *rt_timer_t;
+

下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+
struct rt_timer
+{
+    struct rt_object parent;                            /**< inherit from rt_object */
+
+    rt_list_t        row[RT_TIMER_SKIP_LIST_LEVEL];
+
+    void (*timeout_func)(void *parameter);              /**< timeout function */
+    void            *parameter;                         /**< timeout function's parameter */
+
+    rt_tick_t        init_tick;                         /**< timer timeout tick */
+    rt_tick_t        timeout_tick;                      /**< timeout tick */
+};
+

2)删除定时器

函数声明:

1
+
rt_err_t rt_timer_delete(rt_timer_t timer);
+

函数返回值:返回操作系统的状态,成功返回0,失败返回1

3)动态创建定时器演示

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+
// 主函数
+
+int main(void)
+{
+    tm = rt_timer_create("tm_demo",tm_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
+    if(tm == RT_NULL)
+    {
+        LOG_E("rt_timer_create faile...\n");
+        return -ENOMEM;
+    }
+
+    LOG_D("rt_timer_create successed...\n");
+    return 0;
+}
+

在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义 )。

1
+2
+3
+4
+5
+6
+
// 编写中断回调函数(超时函数)
+
+void tm_callback(void *parameter)
+{
+
+}
+
1
+2
+3
+
// 返回值结构图定义
+
+rt_timer_t tm ; 
+

4)开启定时器

函数声明:

1
+
rt_err_t rt_timer_start(rt_timer_t timer);
+

函数返回值:成功返回0,失败返回1

5)实例:

1
+
rt_timer_start(tm);
+

此时我们在超时函数中编写代码:

1
+2
+3
+4
+
void tm_callback(void *parameter)
+{
+    rt_kprintf("tm_callback is running...\n");
+}
+

此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息

6)静态创建定时器

函数定义:

1
+2
+3
+4
+5
+6
+
void rt_timer_init(rt_timer_t  timer,
+                   const char *name,
+                   void (*timeout)(void *parameter),
+                   void       *parameter,
+                   rt_tick_t   time,
+                   rt_uint8_t  flag);
+

这里我们看下rt_timer_init这个函数的返回值和参数

返回值:void

参数:

参数描述
timer结构体指针类型
name名字
timeout超时回调函数指针
parameter传递给超时回调函数的参数
time定时器时间
flag定时器标志

7)脱离函数(静态创建时使用)

描述:当静态创建的定时器不需要在使用时,我们调用下面这个函数接口

函数声明:

1
+
rt_err_t rt_timer_detach(rt_timer_t timer);
+

返回值:成功返回0,失败返回1

8)定时器控制

函数声明:

1
+
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg);
+

cmd命令定义查看

1
+2
+3
+4
+5
+
#define RT_TIMER_CTRL_SET_TIME          0x0             /**< set timer control command */
+#define RT_TIMER_CTRL_GET_TIME          0x1             /**< get timer control command */
+#define RT_TIMER_CTRL_SET_ONESHOT       0x2             /**< change timer to one shot */
+#define RT_TIMER_CTRL_SET_PERIODIC      0x3             /**< change timer to periodic */
+#define RT_TIMER_CTRL_GET_STATE         0x4             /**< get timer run state active or deactive*/
+

实例:

查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。

在这里插入图片描述

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+#include <rtdbg.h>
+
+rt_timer_t tm ;
+struct rt_timer tm2 ;
+int flags = 0;
+
+void tm_callback(void *parameter)
+{
+    rt_kprintf("tm_callback is running...\n");
+}
+
+void tm2_callback(void *parameter)
+{
+    flags++;
+    if(flags == 10)// 当flags标志位位10时,设置单次触发
+    {
+        rt_timer_control(&tm2, RT_TIMER_CTRL_SET_ONESHOT, NULL);
+        flags = 0;
+    }
+    rt_tick_t timeout = 1000;
+    rt_timer_control(&tm2, RT_TIMER_CTRL_SET_TIME, (void *)&timeout);
+    rt_kprintf("[%u]tm2_callback is running...\n",rt_tick_get());
+}
+
+int main(void)
+{
+    // 动态创建定时器
+    tm = rt_timer_create("tm_demo",tm_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
+    if(tm == RT_NULL)
+    {
+        LOG_E("rt_timer_create faile...\n");
+        return -ENOMEM;
+    }
+
+    LOG_D("rt_timer_create successed...\n");
+    rt_timer_start(tm);
+
+    // 静态创建定时器
+    rt_timer_init(&tm2,"tm2_demo",tm2_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
+    rt_timer_start(&tm2);
+
+    return 0;
+}
+

三、高精度延时

注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间

  • 函数声明:void rt_hw_us_delay(rt_uint32_t us);

  • 应用场景:应用于某些场景下对高精度延时有要求的情况下
+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 13, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621.jpg" new file mode 100644 index 000000000..f712e3930 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621_huad573e2fc4349244e3deecf9a37a5301_121524_250x150_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621_huad573e2fc4349244e3deecf9a37a5301_121524_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..abeae5a79 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.cea367bc964ee037b7721664a278d621_huad573e2fc4349244e3deecf9a37a5301_121524_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.jpg" new file mode 100644 index 000000000..f712e3930 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..4489bdd78 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9c8c94117 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..52d63d10b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo.gif" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo.gif" new file mode 100644 index 000000000..82bd2d541 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo.gif" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif" new file mode 100644 index 000000000..1c6c42e25 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif" new file mode 100644 index 000000000..112714571 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251.png" new file mode 100644 index 000000000..75380e5a7 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png" new file mode 100644 index 000000000..7cba7d95b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png" new file mode 100644 index 000000000..e37b50f57 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275.png" new file mode 100644 index 000000000..2def9c531 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png" new file mode 100644 index 000000000..cafd8caac Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png" new file mode 100644 index 000000000..a26280621 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623.png" new file mode 100644 index 000000000..cd9dd8b7b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png" new file mode 100644 index 000000000..149de8f17 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png" new file mode 100644 index 000000000..66fc38dc8 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831.png" new file mode 100644 index 000000000..7abd9e88d Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png" new file mode 100644 index 000000000..1692abaab Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png" new file mode 100644 index 000000000..553dbaec2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073.png" new file mode 100644 index 000000000..d909f5034 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png" new file mode 100644 index 000000000..67a5defb7 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png" new file mode 100644 index 000000000..e6160d56b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889.png" new file mode 100644 index 000000000..8a915f7b2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png" new file mode 100644 index 000000000..cf43d2244 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png" new file mode 100644 index 000000000..895a07324 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784.png" new file mode 100644 index 000000000..6b8873222 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png" new file mode 100644 index 000000000..0e2f5500e Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png" new file mode 100644 index 000000000..754c9e720 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932.png" new file mode 100644 index 000000000..d23c1802c Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png" new file mode 100644 index 000000000..618a5fd5b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png" new file mode 100644 index 000000000..c38e2b974 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403.png" new file mode 100644 index 000000000..c6dab269e Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png" new file mode 100644 index 000000000..85114b9e0 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png" new file mode 100644 index 000000000..9a5a11d81 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394.png" new file mode 100644 index 000000000..08eb7503b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png" new file mode 100644 index 000000000..1259840bf Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png" new file mode 100644 index 000000000..68cff88db Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453.png" new file mode 100644 index 000000000..66838904a Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png" new file mode 100644 index 000000000..b72483e3f Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png" new file mode 100644 index 000000000..66bd67b6d Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061.png" new file mode 100644 index 000000000..7f3ab9a35 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png" new file mode 100644 index 000000000..3a43dcb15 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png" new file mode 100644 index 000000000..5032e6ab0 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607.png" new file mode 100644 index 000000000..7e8eb8c1b Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png" new file mode 100644 index 000000000..849372227 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png" new file mode 100644 index 000000000..d560715f2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695.png" new file mode 100644 index 000000000..1352893d7 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png" new file mode 100644 index 000000000..29b07bc6e Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png" new file mode 100644 index 000000000..9f3faf0a5 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/index.html" "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/index.html" new file mode 100644 index 000000000..60da3e962 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-thread\347\221\236\350\220\250hmi-board\344\275\277\347\224\250vscode\345\274\200\345\217\221rtduino/index.html" @@ -0,0 +1,930 @@ +【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino +
Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino

【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino

瑞萨HMI-Board使用vscode开发RTduino

+
+

瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled)


1.准备工作

软件环境:

硬件环境:

  • RA6M3-HMI-Board 开发板
  • 0.96寸 ssd1306 oled 显示屏

2.工程配置

首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:

1
+
$ cd rt-thread\bsp\renesas\ra6m3-hmi-board
+

这里需要我们提前安装好 ENV 环境,具体细节请参考 Env编译环境搭建

鼠标右键打开 ENV 工具后,使用 menuconfig 命令打开可视化菜单,勾选上 RTduino 的使能项,保存并退出

image-20240123170636251

1
+2
+3
+4
+
RT-Thread Configuration
+	 → Hardware Drivers Config
+     		→ Onboard Peripheral Drivers
+     				[*] Compatible with Arduino Ecosystem (RTduino)
+

image-20240123171151275

此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):

1
+
$ pkgs --update
+

我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:

image-20240123173108623

3.开始编译

打开 ENV ,同时执行如下命令:

1
+
$ scons -j16
+

image-20240123173509831

在工程编译完成后会生成一个 .elf后缀的可执行文件,到这里工程的编译就顺利结束了。

4.vscode调试配置

首先我们需要在 vscode 中安装 Cortex-Debug 插件,打开 vscode 扩展,搜索 Cortex-Debug并安装扩展:

image-20240123175244073

接下来就是安装 pyocd 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:

1
+
download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases
+

接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 create a launch.json file

image-20240123180230889

之后 vscode 会创建一份 launch.json 文件,我们需要替换文件内容为:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "HMI-Board",
+            "cwd": "${workspaceFolder}",
+            "executable": "${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf",
+            "request": "launch",
+            "type": "cortex-debug",
+            "runToEntryPoint": "main",
+            "targetId": "R7FA6M3AH",
+            "servertype": "pyocd",
+            "serverpath": "D:/compile/sdk-debugger-pyocd/pyocd.bat",
+            "armToolchainPath": "D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin",
+            "gdbPath": "D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe",
+        },
+    ]
+}
+

注意:launch.json文件中的部分参数需要根据具体位置配置

  • serverpath:这部分路径在前面所安装的 sdk-debugger-pyocd位置
  • armToolchainPath:gcc 工具链,找不到位置的可以点击此处下载
  • gdbPath

在完成上述配置后就可以点击 F5 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:

image-20240123183906784

我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:

image-20240123184032932

到这里 RTduino 就已经成功运行在 RT-Thread 啦!

5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled

在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过RTduino,并在RT-Thread中使用 Arduino 源码驱动一个 oled 屏幕。

我们接着回到 ENV 中,使用 menuconfig命令打开菜单,同时使用 shift + /打开搜索界面,并且输入:ssd1306关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 Adafruit SSD1306对应的 2选项,进入点击 y 使能:

image-20240123184834403

image-20240123184930394

这样我们就成功把 Adafruit SSD1306 示例库下载到本地了,同时还有一下依赖库:

image-20240123185120453

我们找到路径:rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c,可以看到该文件夹下有一个ssd1306_128x64_i2c.ino文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的arduino_main.cpp文件中:

1
+
$ cd rt-thread\bsp\renesas\ra6m3-hmi-board\board\rtduino\arduino_main.cpp
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+
/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2023-10-28     Wangyuqiang    first version
+ */
+
+#include <Arduino.h>
+
+#include <SPI.h>
+#include <Wire.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 64 // OLED display height, in pixels
+
+// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
+// The pins for I2C are defined by the Wire-library. 
+// On an arduino UNO:       A4(SDA), A5(SCL)
+// On an arduino MEGA 2560: 20(SDA), 21(SCL)
+// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
+#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
+#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
+
+#define NUMFLAKES     10 // Number of snowflakes in the animation example
+
+#define LOGO_HEIGHT   16
+#define LOGO_WIDTH    16
+static const unsigned char PROGMEM logo_bmp[] =
+{ 0b00000000, 0b11000000,
+  0b00000001, 0b11000000,
+  0b00000001, 0b11000000,
+  0b00000011, 0b11100000,
+  0b11110011, 0b11100000,
+  0b11111110, 0b11111000,
+  0b01111110, 0b11111111,
+  0b00110011, 0b10011111,
+  0b00011111, 0b11111100,
+  0b00001101, 0b01110000,
+  0b00011011, 0b10100000,
+  0b00111111, 0b11100000,
+  0b00111111, 0b11110000,
+  0b01111100, 0b11110000,
+  0b01110000, 0b01110000,
+  0b00000000, 0b00110000 };
+
+void testdrawline();      // Draw many lines
+void testdrawrect(void);      // Draw rectangles (outlines)
+void testfillrect(void);      // Draw rectangles (filled)
+void testdrawcircle(void);    // Draw circles (outlines)
+void testfillcircle(void);    // Draw circles (filled)
+void testdrawroundrect(void); // Draw rounded rectangles (outlines)
+void testfillroundrect(void); // Draw rounded rectangles (filled)
+void testdrawtriangle(void);  // Draw triangles (outlines)
+void testfilltriangle(void);  // Draw triangles (filled)
+void testdrawchar(void);      // Draw characters of the default font
+void testdrawstyles(void);    // Draw 'stylized' characters
+void testscrolltext(void);    // Draw scrolling text
+void testdrawbitmap(void);    // Draw a small bitmap image
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h);
+
+void setup() {
+  Serial.begin(115200);
+
+  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
+    Serial.println(F("SSD1306 allocation failed"));
+    for(;;); // Don't proceed, loop forever
+  }
+
+  // Show initial display buffer contents on the screen --
+  // the library initializes this with an Adafruit splash screen.
+  display.display();
+  delay(2000); // Pause for 2 seconds
+
+  // Clear the buffer
+  display.clearDisplay();
+
+  // Draw a single pixel in white
+  display.drawPixel(10, 10, SSD1306_WHITE);
+
+  // Show the display buffer on the screen. You MUST call display() after
+  // drawing commands to make them visible on screen!
+  display.display();
+  delay(2000);
+  // display.display() is NOT necessary after every single drawing command,
+  // unless that's what you want...rather, you can batch up a bunch of
+  // drawing operations and then update the screen all at once by calling
+  // display.display(). These examples demonstrate both approaches...
+
+  testdrawline();      // Draw many lines
+
+  testdrawrect();      // Draw rectangles (outlines)
+
+  testfillrect();      // Draw rectangles (filled)
+
+  testdrawcircle();    // Draw circles (outlines)
+
+  testfillcircle();    // Draw circles (filled)
+
+  testdrawroundrect(); // Draw rounded rectangles (outlines)
+
+  testfillroundrect(); // Draw rounded rectangles (filled)
+
+  testdrawtriangle();  // Draw triangles (outlines)
+
+  testfilltriangle();  // Draw triangles (filled)
+
+  testdrawchar();      // Draw characters of the default font
+
+  testdrawstyles();    // Draw 'stylized' characters
+
+  testscrolltext();    // Draw scrolling text
+
+  testdrawbitmap();    // Draw a small bitmap image
+
+  // Invert and restore display, pausing in-between
+  display.invertDisplay(true);
+  delay(1000);
+  display.invertDisplay(false);
+  delay(1000);
+
+  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
+}
+
+void loop() {
+}
+
+void testdrawline() {
+  int16_t i;
+
+  display.clearDisplay(); // Clear display buffer
+
+  for(i=0; i<display.width(); i+=4) {
+    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
+    display.display(); // Update screen with each newly-drawn line
+    delay(1);
+  }
+  for(i=0; i<display.height(); i+=4) {
+    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  delay(250);
+
+  display.clearDisplay();
+
+  for(i=0; i<display.width(); i+=4) {
+    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  for(i=display.height()-1; i>=0; i-=4) {
+    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  delay(250);
+
+  display.clearDisplay();
+
+  for(i=display.width()-1; i>=0; i-=4) {
+    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  for(i=display.height()-1; i>=0; i-=4) {
+    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  delay(250);
+
+  display.clearDisplay();
+
+  for(i=0; i<display.height(); i+=4) {
+    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+  for(i=0; i<display.width(); i+=4) {
+    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000); // Pause for 2 seconds
+}
+
+void testdrawrect(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<display.height()/2; i+=2) {
+    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
+    display.display(); // Update screen with each newly-drawn rectangle
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testfillrect(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<display.height()/2; i+=3) {
+    // The INVERSE color is used so rectangles alternate white/black
+    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
+    display.display(); // Update screen with each newly-drawn rectangle
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testdrawcircle(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
+    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testfillcircle(void) {
+  display.clearDisplay();
+
+  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
+    // The INVERSE color is used so circles alternate white/black
+    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
+    display.display(); // Update screen with each newly-drawn circle
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testdrawroundrect(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<display.height()/2-2; i+=2) {
+    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
+      display.height()/4, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testfillroundrect(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<display.height()/2-2; i+=2) {
+    // The INVERSE color is used so round-rects alternate white/black
+    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
+      display.height()/4, SSD1306_INVERSE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testdrawtriangle(void) {
+  display.clearDisplay();
+
+  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
+    display.drawTriangle(
+      display.width()/2  , display.height()/2-i,
+      display.width()/2-i, display.height()/2+i,
+      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testfilltriangle(void) {
+  display.clearDisplay();
+
+  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
+    // The INVERSE color is used so triangles alternate white/black
+    display.fillTriangle(
+      display.width()/2  , display.height()/2-i,
+      display.width()/2-i, display.height()/2+i,
+      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
+    display.display();
+    delay(1);
+  }
+
+  delay(2000);
+}
+
+void testdrawchar(void) {
+  display.clearDisplay();
+
+  display.setTextSize(1);      // Normal 1:1 pixel scale
+  display.setTextColor(SSD1306_WHITE); // Draw white text
+  display.setCursor(0, 0);     // Start at top-left corner
+  display.cp437(true);         // Use full 256 char 'Code Page 437' font
+
+  // Not all the characters will fit on the display. This is normal.
+  // Library will draw what it can and the rest will be clipped.
+  for(int16_t i=0; i<256; i++) {
+    if(i == '\n') display.write(' ');
+    else          display.write(i);
+  }
+
+  display.display();
+  delay(2000);
+}
+
+void testdrawstyles(void) {
+  display.clearDisplay();
+
+  display.setTextSize(1);             // Normal 1:1 pixel scale
+  display.setTextColor(SSD1306_WHITE);        // Draw white text
+  display.setCursor(0,0);             // Start at top-left corner
+  display.println(F("Hello, world!"));
+
+  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
+  display.println(3.141592);
+
+  display.setTextSize(2);             // Draw 2X-scale text
+  display.setTextColor(SSD1306_WHITE);
+  display.print(F("0x")); display.println(0xDEADBEEF, HEX);
+
+  display.display();
+  delay(2000);
+}
+
+void testscrolltext(void) {
+  display.clearDisplay();
+
+  display.setTextSize(2); // Draw 2X-scale text
+  display.setTextColor(SSD1306_WHITE);
+  display.setCursor(10, 0);
+  display.println(F("scroll"));
+  display.display();      // Show initial text
+  delay(100);
+
+  // Scroll in various directions, pausing in-between:
+  display.startscrollright(0x00, 0x0F);
+  delay(2000);
+  display.stopscroll();
+  delay(1000);
+  display.startscrollleft(0x00, 0x0F);
+  delay(2000);
+  display.stopscroll();
+  delay(1000);
+  display.startscrolldiagright(0x00, 0x07);
+  delay(2000);
+  display.startscrolldiagleft(0x00, 0x07);
+  delay(2000);
+  display.stopscroll();
+  delay(1000);
+}
+
+void testdrawbitmap(void) {
+  display.clearDisplay();
+
+  display.drawBitmap(
+    (display.width()  - LOGO_WIDTH ) / 2,
+    (display.height() - LOGO_HEIGHT) / 2,
+    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
+  display.display();
+  delay(1000);
+}
+
+#define XPOS   0 // Indexes into the 'icons' array in function below
+#define YPOS   1
+#define DELTAY 2
+
+void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
+  int8_t f, icons[NUMFLAKES][3];
+
+  // Initialize 'snowflake' positions
+  for(f=0; f< NUMFLAKES; f++) {
+    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
+    icons[f][YPOS]   = -LOGO_HEIGHT;
+    icons[f][DELTAY] = random(1, 6);
+    Serial.print(F("x: "));
+    Serial.print(icons[f][XPOS], DEC);
+    Serial.print(F(" y: "));
+    Serial.print(icons[f][YPOS], DEC);
+    Serial.print(F(" dy: "));
+    Serial.println(icons[f][DELTAY], DEC);
+  }
+
+  for(;;) { // Loop forever...
+    display.clearDisplay(); // Clear the display buffer
+
+    // Draw each snowflake:
+    for(f=0; f< NUMFLAKES; f++) {
+      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
+    }
+
+    display.display(); // Show the display buffer on the screen
+    delay(200);        // Pause for 1/10 second
+
+    // Then update coordinates of each flake...
+    for(f=0; f< NUMFLAKES; f++) {
+      icons[f][YPOS] += icons[f][DELTAY];
+      // If snowflake is off the bottom of the screen...
+      if (icons[f][YPOS] >= display.height()) {
+        // Reinitialize to a random position, just off the top
+        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
+        icons[f][YPOS]   = -LOGO_HEIGHT;
+        icons[f][DELTAY] = random(1, 6);
+      }
+    }
+  }
+}
+

在此示例中有几点注意事项:

  • 在每一份添加的示例工程中,我们都必须要包含头文件 #include <Arduino.h>
  • 由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 0x3c,所以对应示例工程中的 SCREEN_ADDRESS需要修改为 0X3C

image-20240123190157061

  • 由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍

image-20240123190348607

接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:

pinfunc
P203i2c0-sda
P202i2c0-scl
VCCvcc
GNDgnd

接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程

image-20240123191534695

查看demo:

demo

+Licensed under CC BY-NC-SA 4.0
+Last updated on Feb 18, 2024 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/index.html" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/index.html" new file mode 100644 index 000000000..62234c8f5 --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\347\256\241\347\220\206/index.html" @@ -0,0 +1,217 @@ +线程管理 +
Featured image of post 线程管理

线程管理

在 RT-Thread 中,线程是实现任务的载体,它是 RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。

+
+

原理实战请查看【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)

一、序言

在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 +同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。

下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:

1.读取数据 +2.显示数据

简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 +在这里插入图片描述 +在RT-Thread 中,与上述子任务对应的程序实体就是线程,线程是实现任务的载体。 +它是RT-Thread中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 +上下文:当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。

二、线程管理的功能特点

RT-Thread 线程管理的主要功能是对线程进行管理和调度,系统中总共存在两类线程,分别是系统线程用户线程。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。

如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 +在这里插入图片描述

  • RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。
  • 当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。
  • 当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(详细内容可参考【操作系统】进程上下文和线程上下文)信息恢复。

三、线程的工作机制

1.线程控制块

在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
/* 线程控制块*/
+struct rt_thread
+{
+	/* rt 对象*/
+	char name[RT_NAME_MAX]; /* 线程名称*/
+	rt_uint8_t type; /* 对象类型*/
+	rt_uint8_t flags; /* 标志位*/
+	rt_list_t list; /* 对象列表*/
+	rt_list_t tlist; /* 线程列表*/
+
+	/* 栈指针与入口指针*/
+	void *sp; /* 栈指针*/
+	void *entry; /* 入口函数指针*/
+	void *parameter; /* 参数*/
+	void *stack_addr; /* 栈地址指针*/
+	rt_uint32_t stack_size; /* 栈大小*/
+
+	/* 错误代码*/
+	rt_err_t error; /* 线程错误代码*/
+	rt_uint8_t stat; /* 线程状态*/
+
+	/* 优先级*/
+	rt_uint8_t current_priority; /* 当前优先级*/
+	rt_uint8_t init_priority; /* 初始优先级*/
+	rt_uint32_t number_mask;
+	......
+	rt_ubase_t init_tick; /* 线程初始化计数值*/
+	rt_ubase_t remaining_tick; /* 线程剩余计数值*/
+
+	struct rt_timer thread_timer; /* 内置线程定时器*/
+
+	void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/
+	rt_uint32_t user_data; /* 用户数据*/
+};
+
  • 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。
  • cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。
  • 最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。

2.线程的重要属性

(1) 线程栈

  • RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。
  • 线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。
  • 对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。
  • 线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 +在这里插入图片描述

(2) 线程状态

线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 +在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:

状态描述
初始态当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT
就绪态在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY
运行态线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING
挂起态也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND
关闭态当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE

(3) 线程优先级

  • RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。

  • RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。

(4) 时间片

每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。

假设有2 个优先级相同的就绪态线程A 与B,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 +在这里插入图片描述

(5) 线程的入口函数

线程控制块中的entry是线程的入口函数,它是线程实现预期功能的函数。

线程的入口函数由用户设计实现,一般有以下两种代码形式: +1.无限循环模式

在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 +界事件的发生,而后进行相应的服务:

1
+2
+3
+4
+5
+6
+7
+8
+
void thread_entry(void* paramenter)
+{
+while (1)
+	{
+		/* 等待事件的发生*/
+		/* 对事件进行服务、进行处理*/
+	}
+}
+

作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 +所以在实时操作系统中必须注意的一点就是:线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。

2.顺序执行或有限次循环模式

如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。

1
+2
+3
+4
+5
+6
+7
+8
+
static void thread_entry(void* parameter)
+{
+	/* 处理事务#1 */
+	…
+	/* 处理事务#2 */
+	…
+	/* 处理事务#3 */
+}
+

(6) 常见的线程错误码

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
#define RT_EOK 0 /* 无错误*/
+#define RT_ERROR 1 /* 普通错误*/
+#define RT_ETIMEOUT 2 /* 超时错误*/
+#define RT_EFULL 3 /* 资源已满*/
+#define RT_EEMPTY 4 /* 无资源*/
+#define RT_ENOMEM 5 /* 无内存*/
+#define RT_ENOSYS 6 /* 系统不支持*/
+#define RT_EBUSY 7 /* 系统忙*/
+#define RT_EIO 8 /* IO 错误*/
+#define RT_EINTR 9 /* 中断系统调用*/
+#define RT_EINVAL 10 /* 非法参数*/
+

3.线程状态切换

RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: +在这里插入图片描述

  • 线程通过调用函数rt_thread_create/init() 进入到初始状态(RT_THREAD_INIT)
  • 初始状态的线程通过调用函数rt_thread_startup() 进入到就绪状态(RT_THREAD_READY)
  • 就绪状态的线程被调度器调度后进入运行状态(RT_THREAD_RUNNING)
  • 当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态(RT_THREAD_SUSPEND)
  • 处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。
  • 挂起状态的线程,如果调用rt_thread_delete/detach() 函数,将更改为关闭状态(RT_THREAD_CLOSE)
  • 而运行状态的线程,如果运行结束,就会在线程的最后部分执行rt_thread_exit() 函数,将状态更改为关闭状态。

!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。

4.系统线程

系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。

(1)空闲线程

空闲线程是系统创建的最低优先级的线程,线程状态永远为就绪态。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。

另外,空闲线程在RT-Thread 也有着它的特殊用途:

  • 若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。
  • 空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于钩子函数看门狗不懂的可以看这里)

(2) 主线程

在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。

过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 +在这里插入图片描述

四、线程的管理方式

可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。

动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。

下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 +在这里插入图片描述

1.创建和删除线程

(1)创建线程

一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:

1
+2
+3
+4
+5
+6
+
rt_thread_t rt_thread_create(const char* name,
+							 void (*entry)(void* parameter),
+							 void* parameter,
+							 rt_uint32_t stack_size,
+							 rt_uint8_t priority,
+							 rt_uint32_t tick);
+

调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。

线程创建rt_thread_create() 的参数和返回值见下图: +在这里插入图片描述

(2)删除线程

对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:

rt_err_t rt_thread_delete(rt_thread_t thread);
+

调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。

线程删除rt_thread_delete() 接口的参数和返回值见下图: +在这里插入图片描述 +这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。

2.初始化和脱离线程

(1)初始化线程

线程的初始化可以使用下面的函数接口完成,来初始化静态线程对象:

1
+2
+3
+4
+5
+
rt_err_t rt_thread_init(struct rt_thread* thread,
+					    const char* name,
+						void (*entry)(void* parameter), void* parameter,
+						void* stack_start, rt_uint32_t stack_size,
+						rt_uint8_t priority, rt_uint32_t tick);
+

在这里插入图片描述

(2)脱离线程

对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:

rt_err_t rt_thread_detach (rt_thread_t thread);
+
参数描述
thread线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。
返回
RT_EOK线程脱离成功
-RT_ERROR线程脱离失败

3.启动线程

创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:

rt_err_t rt_thread_startup(rt_thread_t thread);
+

在这里插入图片描述

当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 +动的线程优先级比当前线程优先级高,将立刻切换到这个线程。

4.获得当前线程

在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:

rt_thread_t rt_thread_self(void);
+

在这里插入图片描述

5.使线程出让处理器资源

当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。

线程让出处理器使用下面的函数接口:

rt_err_t rt_thread_yield(void);
+

调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。

6.使线程睡眠

在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。

线程睡眠可使用以下三个函数接口:

1
+2
+3
+
rt_err_t rt_thread_sleep(rt_tick_t tick);
+rt_err_t rt_thread_delay(rt_tick_t tick);
+rt_err_t rt_thread_mdelay(rt_int32_t ms);
+

在这里插入图片描述

7.挂起和恢复线程

(1)线程挂起

  • 当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。
  • 处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。

线程挂起使用下面的函数接口:

rt_err_t rt_thread_suspend (rt_thread_t thread);
+

在这里插入图片描述 +!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。

(2)恢复线程

恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 +所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。

线程恢复使用下面的函数接口:

rt_err_t rt_thread_resume (rt_thread_t thread);
+

在这里插入图片描述

8.控制线程

当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:

rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg);
+

在这里插入图片描述

指示控制命令cmd 当前支持的命令包括:
+•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级;
+•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用;
+•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。
+

设置和删除空闲钩子

空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。

设置/ 删除空闲钩子的接口如下:

rt_err_t rt_thread_idle_sethook(void (*hook)(void));
+rt_err_t rt_thread_idle_delhook(void (*hook)(void));
+
参数描述
hook设置/删除的钩子函数
返回
RT-EOK设置/删除成功
-RT_EFULL设置失败
-RT_ENOSYS删除失败

!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。

10.设置调度器钩子

在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。

在系统线程切换时,这个钩子函数将被调用:

void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to));
+

设置调度器钩子函数的输入参数如下表所示:

参数描述
hook表示用户定义的钩子函数指针

钩子函数hook() 的声明如下:

void hook(struct rt_thread* from, struct rt_thread* to);
+
参数描述
from表示系统所要切换出的线程控制块指针
to表示系统所要切换到的线程控制块指针

!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。


资料参考: +(1)【STM32】HAL库 STM32CubeMX教程五—-看门狗(独立看门狗,窗口看门狗) +(2)什么是钩子函数 +(3)RT-Thread文档中心

+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 16, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/index.html" "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/index.html" new file mode 100644 index 000000000..762ecafde --- /dev/null +++ "b/p/\347\216\251\350\275\254rt-thread\347\272\277\347\250\213\351\227\264\345\220\214\346\255\245-\344\277\241\345\217\267\351\207\217/index.html" @@ -0,0 +1,281 @@ +线程间同步 信号量 +
Featured image of post 线程间同步 信号量

线程间同步 信号量

信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。

+
+

一、概述:

多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:

信号量(semaphore)、互斥量(mutex)、和事件集(event)

二、信号量

1、简述

信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步互斥的目的。

信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例(资源)。

2、信号量结构体

1
+2
+3
+4
+5
+6
+7
+
struct rt_semaphore
+{
+    struct rt_ipc_object parent;                        /**< 继承自ipc_object类 */
+
+    rt_uint16_t          value;                         /**< value of semaphore. */
+    rt_uint16_t          reserved;                      /**< reserved field 预留*/
+};
+

当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。

3、信号量使用及管理

对一个信号量的操作包含:创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量

1)动态创建信号量

当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。

当选择 RT_IPC_FLAG_FIFO(先进先出)方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; +当选择 RT_IPC_FLAG_PRIO(优先级等待)方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。

函数声明

rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);

参数介绍

注意:

(1)此处的*name定义最多只能显示八个字符

(2)查看rt_sem_create()函数返回值是-->typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore

1
+2
+3
+4
+
// flag值	如下
+
+#define RT_IPC_FLAG_FIFO                0x00            /**< FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */
+#define RT_IPC_FLAG_PRIO                0x01            /**< PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */
+

2)动态创建的信号量删除

系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。

调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。

函数声明 +rt_err_t rt_sem_delete(rt_sem_t sem);

实例

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+#include <rtdbg.h>
+
+rt_sem_t sem1;
+
+
+int main(void)
+{
+    sem1 = rt_sem_create("sem_1",1,RT_IPC_FLAG_FIFO);
+    if(sem1 == RT_NULL)
+    {
+        LOG_E("rt_sem_create is failure...\n");
+    }
+
+    LOG_D("rt_sem_create is success...\n");
+    return 0;
+}
+

3)静态创建信号量

描述

对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。

函数声明

1
+2
+3
+4
+
rt_err_t rt_sem_init(rt_sem_t    sem,
+                     const char *name,
+                     rt_uint32_t value,
+                     rt_uint8_t  flag);
+

参数描述

4)脱离信号量

描述

脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于静态初始化的信号量

函数声明

1
+
rt_err_t rt_sem_detach(rt_sem_t sem);
+

5)获取信号量

描述

线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。

如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。

如果在参数 time 指定的时间内依然得不到信号量,线程将超时返回,返回值是 - RT_ETIMEOUT

函数声明

1
+
rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time);
+

参数描述

1
+2
+3
+4
+
// time参数
+
+#define RT_WAITING_FOREVER              -1              /**< Block forever until get resource. */
+#define RT_WAITING_NO                   0               /**< Non-block. */
+
1
+2
+3
+4
+5
+
// 扩展:
+
+rt_err_t rt_sem_trytake(rt_sem_t sem); // 无等待获取信号量
+
+// 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。
+

6)信号量释放

函数声明

1
+
rt_err_t rt_sem_release(rt_sem_t sem);
+

描述

例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。

4、信号量实例演示

这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态

在这里插入图片描述

由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态

在这里插入图片描述

查看信号量设定的标志位是RT_IPC_FLAG_FIFO,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1->线程2->线程1->线程2…的顺序执行的,这样就实现了线程的并发互斥运行。

在这里插入图片描述

在这里插入图片描述

最后附上测试源代码

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+
#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+#include <rtdbg.h>
+
+rt_sem_t sem1;
+struct rt_semaphore sem2;
+
+rt_thread_t th1,th2;
+
+int flags = 0;
+
+void th1_entry(void *parameter)
+{
+    while(1)
+    {
+        rt_thread_mdelay(8000);
+        rt_sem_take(sem1, RT_WAITING_FOREVER);// 获取信号量
+        flags++;
+        if(flags == 100)
+            flags = 0;
+        rt_kprintf("th1_entry [%d]\n",flags);
+        rt_sem_release(&sem2);// 对获取的信号量进行释放
+    }
+}
+
+void th2_entry(void *parameter)
+{
+    while(1)
+    {
+        rt_sem_take(&sem2, RT_WAITING_FOREVER);// 获取信号量
+        if(flags > 0)
+            flags--;
+        rt_kprintf("th2_entry [%d]\n",flags);
+        rt_sem_release(sem1);// 对获取的信号量进行释放
+        rt_thread_mdelay(1000);
+    }
+}
+
+int main(void)
+{
+    int ret = 0;
+    sem1 = rt_sem_create("sem_1",1,RT_IPC_FLAG_FIFO);
+    if(sem1 == RT_NULL)
+    {
+        LOG_E("sem1 rt_sem_create is failure...\n");
+    }
+
+    LOG_D("sem1 rt_sem_create is success...\n");
+
+    ret = rt_sem_init(&sem2, "sem2", 0, RT_IPC_FLAG_FIFO);
+    if(ret < 0)
+    {
+        LOG_E("sem2 rt_sem_create is failure...\n");
+        return ret;
+    }
+
+    LOG_D("sem2 rt_sem_init successed...\n");
+
+    th1 = rt_thread_create("th1", th1_entry, NULL, 512, 20, 5);
+    if(th1 == RT_NULL)
+    {
+        LOG_E("th1 rt_thread_create failed...\n");
+        return -ENOMEM;
+    }
+
+    LOG_D("th1 rt_thread_create successed...\n");
+
+    th2 = rt_thread_create("th2", th2_entry, NULL, 512, 20, 5);
+    if(th2 == RT_NULL)
+    {
+        LOG_E("th2 rt_thread_create failed...\n");
+        return -ENOMEM;
+    }
+
+    LOG_D("th2 rt_thread_create successed...\n");
+
+    rt_thread_startup(th1);
+    rt_thread_startup(th2);
+    return 0;
+}
+
+Licensed under CC BY-NC-SA 4.0
+Last updated on Jul 17, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f8d077909 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.f69303bf342dd5617e5c4cf3d54c94cb_hu40687f202fa630f90f24f65ce5d02641_5793_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.jpg" new file mode 100644 index 000000000..ee6ce9389 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..9ef548ca1 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..ae199ede2 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..08db6f6a2 Binary files /dev/null and "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/cover_hu40687f202fa630f90f24f65ce5d02641_5793_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/index.html" "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/index.html" new file mode 100644 index 000000000..61a32feeb --- /dev/null +++ "b/p/\347\221\236\350\220\250ra6m4\345\274\200\345\217\221\346\235\277\345\234\250rt-thread\344\270\255\344\275\277\347\224\250segger_rtt\350\275\257\344\273\266\345\214\205/index.html" @@ -0,0 +1,173 @@ +瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包 +
Featured image of post 瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包

瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包

瑞萨RA6M4开发板使用示例<RT-Thread的版本为v4.1.0及以上>

+
+

一、创建工程,选择SEGGER_RTT软件包

image-20221003133030692

image-20221003133219108

2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ]

rt_console_set_device前调用rt_hw_jlink_rtt_init初始化函数

image-20221003133721333

3、控制台对接上jlinkRtt

1
+2
+3
+
rtconfg.h
+
+// 修改RT_CONSOLE_DEVICE_NAME为空
+

image-20221003134935152

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
shell.c [ 路径:D:\rt-thread\components\finsh\shell.c]
+
+/* 1、首先添加以下头文件 */
+#include "SEGGER_RTT.h"
+#include "SEGGER_RTT_Conf.h"
+
+/* 2、修改finsh_getchar */
+int finsh_getchar(void)
+{
+#ifdef RT_USING_DEVICE
+    char ch = 0;
+#ifdef RT_USING_POSIX_STDIO
+    if(read(STDIN_FILENO, &ch, 1) > 0)
+    {
+        return ch;
+    }
+    else
+    {
+        return -1; /* EOF */
+    }
+#else
+    rt_device_t device;
+
+    RT_ASSERT(shell != RT_NULL);
+
+    device = shell->device;
+    if (device == RT_NULL)
+    {
+        extern char rt_hw_console_getchar(void);
+        return rt_hw_console_getchar();
+    }
+
+    while (rt_device_read(device, -1, &ch, 1) != 1)
+    {
+        rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);
+        if (shell->device != device)
+        {
+            device = shell->device;
+            if (device == RT_NULL)
+            {
+                return -1;
+            }
+        }
+    }
+
+    return ch;
+#endif /* RT_USING_POSIX_STDIO */
+#else
+    extern char rt_hw_console_getchar(void);
+    return rt_hw_console_getchar();
+#endif /* RT_USING_DEVICE */
+}
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
kservice.c [ 路径:\rt-thread\src\kservice.c ]
+// 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output 
+
+RT_WEAK void rt_hw_console_output(const char *str)
+{
+    /* empty console output */
+    rt_size_t i = 0, size = 0;
+
+    size = rt_strlen(str);
+    for (i = 0; i < size; i++)
+    {
+        if (*(str + i) == '\n')
+        {
+           break;
+        }
+    }
+    SEGGER_RTT_printf(0,"%s",str);
+}
+RTM_EXPORT(rt_hw_console_output);
+

4、实验效果

首先确保已经下载好J-Link RTT Viewer,直接去官网下载最新版本即可

然后编译和下载工程,注意下载方式为J-Link

双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看_SEGGER_RTT变量地址(全局搜索即可,找到.bss._SEGGER_RTT)

image-20221003140449806

打开J-Link RTT Viewer

image-20221003140736161

此时就可以正常使用segger_rtt了!

image-20221003140911791

+Licensed under CC BY-NC-SA 4.0
+Last updated on Aug 22, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d.jpg" new file mode 100644 index 000000000..3934b55b9 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..0b4b62783 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.c1157b8f4e257eef1a5510adae61b83d_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.jpg" new file mode 100644 index 000000000..3934b55b9 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..16f7afe15 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..6f08bd14f Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..f0fc33872 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/index.html" new file mode 100644 index 000000000..4adb1eec2 --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253arm\345\270\270\347\224\250\346\261\207\347\274\226\346\214\207\344\273\244/index.html" @@ -0,0 +1,25 @@ +【经验分享】ARM常用汇编指令 +
Featured image of post 【经验分享】ARM常用汇编指令

【经验分享】ARM常用汇编指令

ARM常用汇编指令

+
+

ARM常用汇编指令

指令名称作用
EQU给数字常量设置一个符号名,相当于C语言中的define
AREA汇编一个新的代码段或者数据段
SPACE分配内存空间
PRESERVE8当前文件栈需要按照8字节对齐
EXPORT声明一个符号具有全局属性,可被外部文件使用
DCD以字为单位分配内存,要求4字节对齐,并要求初始化这些内存
PROC定义子程序,与ENDP成对使用,表示子程序结束
WEAK弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便
IMPORT声明标号来自外部文件,与C语言的EXETERN关键字类似
B跳转到一个标号
ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便
END到达文件的末尾,文件结束
IF,ELSE,ENDIF汇编条件分支语句,与C语言的if else类似
MRS加载特殊功能寄存器的值到特殊功能寄存器
CBZ比较,如果结果为0则转移
CBNZ比较,如果结果非0则转移
LDR从存储器中加载字到一个寄存器中
LDR[伪指令]加载一个立即数或者一个地址到一个寄存器中。
LDRH从存储器中加载半字到一个寄存器中
LDRB从存储器中加载字节到一个寄存器中
STR把一个寄存器按字节存储到存储器中
STRH把一个寄存器的低半字存储到存储器中
STRB把一个寄存器的低字节存储到存储器中
LDMIA加载多个字,并且在加载后自增基址寄存器
STMIA存储多个字,并且在存储后自增基址寄存器
ORR按位或
BX直接跳转到由寄存器给定的地址
BL跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR
BLX跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错
+Licensed under CC BY-NC-SA 4.0
+Last updated on Mar 29, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c.jpg" new file mode 100644 index 000000000..59156ed7a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c_huba1532e2363e5b99fb24669319d872ca_177311_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c_huba1532e2363e5b99fb24669319d872ca_177311_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..ff5489094 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.0cddc637c7dd4ac30d7c72c1eacc4e7c_huba1532e2363e5b99fb24669319d872ca_177311_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.jpg" new file mode 100644 index 000000000..59156ed7a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..4b03ec8cf Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..9d168da0a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..42671ae61 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/cover_huba1532e2363e5b99fb24669319d872ca_177311_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/index.html" new file mode 100644 index 000000000..485d8e1f9 --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253linux\347\216\257\345\242\203\344\270\213v2ray\347\232\204\344\275\277\347\224\250/index.html" @@ -0,0 +1,37 @@ +【经验分享】Linux环境下v2ray的使用 +
Featured image of post 【经验分享】Linux环境下v2ray的使用

【经验分享】Linux环境下v2ray的使用

Linux 环境下v2ray的使用

+
+

Linux 环境下v2ray的使用


v2ray官方文档:https://v2raya.org/

curl安装

1
+2
+
apt-get purge libcurl4
+apt-get install curl
+

v2ray镜像脚本安装

1
+
curl -Ls https://mirrors.v2raya.org/go.sh | sudo bash
+

image-20230504104013149

出现该提示信息则表示安装成功:info: V2Ray v5.4.1 is installed.

接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray

1
+
sudo systemctl disable v2ray --now 
+

v2ray软件安装

仓库release地址:https://github.com/v2rayA/v2rayA/releases

选择合适自己 Linux 内核架构,可以使用dpkg --print-architecture查看

image-20230504105029122

这里我选择``下载到 Linux 共享文件夹

image-20230504105226313

将共享文件夹下的installer_debian_amd64_2.0.5.deb文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装

image-20230504105440300

image-20230504105340371

启动v2raya进程

1
+
sudo systemctl start v2raya.service
+

设置开机自启动

1
+
sudo systemctl enable v2raya.service
+

v2ray使用

打开火狐浏览器,输入 http://localhost:2017/

输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建

image-20230504105825544

导入我们的机场订阅地址

image-20230504105925321

选择想要使用的节点后,点击 Ready

image-20230504110635073

v2ray Settings

我们点击网页上右上角的Setting,进行如下修改

image-20230504111011073

测试

至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了

image-20230504111116983

+Licensed under CC BY-NC-SA 4.0
+Last updated on May 04, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985.jpg" new file mode 100644 index 000000000..9160d54a4 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..a30473195 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.jpg" new file mode 100644 index 000000000..9160d54a4 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c1754452e Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..8a14295e5 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..4c6db423c Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/index.html" new file mode 100644 index 000000000..001cb94fe --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253microsoft-visual-c-14.0-\345\256\211\350\243\205\345\217\212pycocotools2.0\347\211\210\346\234\254\345\256\211\350\243\205\346\225\231\345\255\246\351\230\262\350\270\251\345\235\221/index.html" @@ -0,0 +1,35 @@ +Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑) +
Featured image of post Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)

Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)

Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学

+
+

1、Microsoft Visual C++ 14.0安装

这里附上百度网盘下载链接: +链接: https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88 提取码: ec88

下载完成后双击打开 +在这里插入图片描述

默认下载方式即可


2、Pycocotools2.0版本安装

(1)准备材料:

(2)源码配置

打开下载好的pycocotools,双击打开setup.py(文件路径:\cocoapi\PythonAPI\setup.py)

在这里插入图片描述

这里将蓝色部分删除,只保留红色部分(切记需要执行这一步!!!)

开始界面找到所有应用并打开Anaconda Powershell Prompt

先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。

如上图所示进入到\cocoapi\PythonAPI该目录下

分别执行以下两个命令:

1
+2
+
python setup.py build_ext --inplace
+python setup.py build_ext install
+

在这里插入图片描述

执行pip list查看

+此时回到\cocoapi\PythonAPI目录下,可以看到生成了相关文件 +在这里插入图片描述 +将pycocotoolspycocotools.egg-info文件夹复制到你所创建的虚拟环境中(位置:Anaconda3->envs->python_env->Lib->site-packages) +在这里插入图片描述

至此所有问题解决!

+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 12, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a.jpg" new file mode 100644 index 000000000..fb4e0a8e0 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a_hu042cdab30ea052232a927d02c15faadc_94256_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a_hu042cdab30ea052232a927d02c15faadc_94256_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..f50c301c1 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.48a209866d99b4439c5b44f085860b9a_hu042cdab30ea052232a927d02c15faadc_94256_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.jpg" new file mode 100644 index 000000000..fb4e0a8e0 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..7ad355c50 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..c4e6fe90b Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..3234bdb74 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/cover_hu042cdab30ea052232a927d02c15faadc_94256_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/index.html" new file mode 100644 index 000000000..0ef68868a --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wireshark\347\275\221\347\273\234\346\212\223\345\214\205\346\225\231\347\250\213/index.html" @@ -0,0 +1,26 @@ +Wireshark网络抓包教程 +
Featured image of post Wireshark网络抓包教程

Wireshark网络抓包教程

Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。

+
+

来源:转自:WireShark 抓包使用教程–详细

前言

Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:

1、Wireshark软件下载和安装以及Wireshark主界面介绍。

2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。

3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。

Wireshark软件安装

软件下载路径:wireshark官网。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。

如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:win10pcap兼容性安装包

Wireshark 开始抓包示例

先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。

1、打开wireshark 2.6.5,主界面如下:

image-20230410204240214

2、选择菜单栏上Capture -> Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。

image-20230410204301558

3、wireshark启动后,wireshark处于抓包状态中。

image-20230410204330881

4、执行需要抓包的操作,如ping www.baidu.com

5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。

image-20230410204349768

5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。

Wireshakr抓包界面

image-20230410204417023

说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --> Coloring Rules。如下所示

image-20230410204435065

WireShark 主要分为这几个界面

1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --> Display Filters。

image-20230410204500320

2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。

image-20230410204525166

3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为

(1)Frame: 物理层的数据帧概况

(2)Ethernet II: 数据链路层以太网帧头部信息

(3)Internet Protocol Version 4: 互联网层IP包头部信息

(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP

(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议

image-20230410204540297

TCP包的具体内容

从下图可以看到wireshark捕获到的TCP包中的每个字段。

image-20230410204557194

4. Dissector Pane(数据包字节区)。

Wireshark过滤器设置

初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。

(1)抓包过滤器

捕获过滤器的菜单栏路径为Capture --> Capture Filters。用于在抓取数据包前设置。

image-20230410204620124

如何使用?可以在抓取数据包前设置如下。

image-20230410204653927

ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:

image-20230410204717268

(2)显示过滤器

显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下

image-20230410204734985

执行ping www.huawei.com获取的数据包列表如下

image-20230410204753507

观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。

image-20230410204815301

上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。

wireshark过滤器表达式的规则

1、抓包过滤器语法和实例

抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&& 与、|| 或、!非)

(1)协议过滤

比较简单,直接在抓包过滤框中直接输入协议名即可。

TCP,只显示TCP协议的数据包列表

HTTP,只查看HTTP协议的数据包列表

ICMP,只显示ICMP协议的数据包列表

(2)IP过滤

host 192.168.1.104

src host 192.168.1.104

dst host 192.168.1.104

(3)端口过滤

port 80

src port 80

dst port 80

(4)逻辑运算符&& 与、|| 或、!非

src host 192.168.1.104 && dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包

host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包

!broadcast 不抓取广播数据包

2、显示过滤器语法和实例

(1)比较操作符

比较操作符有== 等于、!= 不等于、> 大于、< 小于、>= 大于等于、<=小于等于。

(2)协议过滤

比较简单,直接在Filter框中直接输入协议名即可。注意:协议名称需要输入小写。

tcp,只显示TCP协议的数据包列表

http,只查看HTTP协议的数据包列表

icmp,只显示ICMP协议的数据包列表

image-20230410204852057

(3) ip过滤

ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表

ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表

ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表

image-20230410204937591

(4)端口过滤

tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。

tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。

tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。

image-20230410204953546

(5) Http模式过滤

http.request.method==“GET”, 只显示HTTP GET方法的。

(6)逻辑运算符为 and/or/not

过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp

image-20230410205019907

(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下

image-20230410205039366

右键单击选中后出现如下界面

image-20230410205054595

选中Select后在过滤器中显示如下

image-20230410205109402

后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含"abcd"内容的数据流。包含的关键词是contains 后面跟上内容。

image-20230410205121718

看到这, 基本上对wireshak有了初步了解。

Wireshark抓包分析TCP三次握手

(1)TCP三次握手连接建立过程

Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;

Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;

Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。

image-20230410205135665

(2)wireshark抓包获取访问指定服务端数据包

Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。

Step2:使用ping www.huawei.com获取IP。

image-20230410205150253

Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183

image-20230410205200760

图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。

第一次握手数据包

客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。

image-20230410205215079

数据包的关键属性如下:

SYN :标志位,表示请求建立连接

Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据

Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据

第二次握手的数据包

服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图

image-20230410205230236

数据包的关键属性如下:

[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK

Seq = 0 :初始建立值为0,表示当前还没有发送数据

Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)

第三次握手的数据包

客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:

image-20230410205245006

数据包的关键属性如下:

ACK :标志位,表示已经收到记录

Seq = 1 :表示当前已经发送1个数据

Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。

就这样通过了TCP三次握手,建立了连接。开始进行数据交互

image-20230410205305433

下面针对数据交互过程的数据包进行一些说明:

image-20230410205320467

数据包的关键属性说明

Seq: 1

Ack: 1: 说明现在共收到1字节数据

image-20230410205335911

Seq: 1
Ack: 951: 说明现在服务端共收到951字节数据

在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下

image-20230410205349152

其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。

Wireshark分析常用操作

调整数据包列表中时间戳显示格式。调整方法为View -->Time Display Format --> Date and Time of Day。调整后格式如下:

image-20230410205401641

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a.jpg" new file mode 100644 index 000000000..dac88baf9 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a_hua939fa00c4e9286056c5c99bbb532251_65046_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a_hua939fa00c4e9286056c5c99bbb532251_65046_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..d1dfd06bd Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.544227d1dfcaa00da5f349b192d3b56a_hua939fa00c4e9286056c5c99bbb532251_65046_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.jpg" new file mode 100644 index 000000000..dac88baf9 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..67f97bf23 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..44c45c66a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..da4a6fec0 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/cover_hua939fa00c4e9286056c5c99bbb532251_65046_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png.webp" new file mode 100644 index 000000000..d5ba3820b Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..c92d2e561 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..8502441cc Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96.png" new file mode 100644 index 000000000..5130e957c Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png" new file mode 100644 index 000000000..f81ee7d23 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png" new file mode 100644 index 000000000..7aa663d8b Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" new file mode 100644 index 000000000..8df766438 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png" new file mode 100644 index 000000000..b28a04bc6 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png" new file mode 100644 index 000000000..5b70576ac Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png.webp" new file mode 100644 index 000000000..be07bf1de Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..98b3531cb Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..dc7ce12cc Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" new file mode 100644 index 000000000..b0db7d33a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..c53479d1a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..e9c5017fa Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" new file mode 100644 index 000000000..dac88baf9 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..a022e4caa Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp" new file mode 100644 index 000000000..d95ebe765 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7.png" new file mode 100644 index 000000000..85cba68f3 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png" new file mode 100644 index 000000000..6753df596 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png" new file mode 100644 index 000000000..47d48a485 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac.png" new file mode 100644 index 000000000..c83c6769e Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png" new file mode 100644 index 000000000..7153f50a6 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png" new file mode 100644 index 000000000..8b2dd70ec Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/index.html" new file mode 100644 index 000000000..99c31998d --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253wsl\344\270\255\344\275\277\347\224\250usb\350\256\276\345\244\207/index.html" @@ -0,0 +1,103 @@ +【经验分享】WSL中使用USB设备 +
Featured image of post 【经验分享】WSL中使用USB设备

【经验分享】WSL中使用USB设备

本文就WSL中无法使用主机USB设备背景下,通过编译linux内核启用USB设备功能

+
+

具体步骤:

首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:

下载链接:https://github.com/dorssel/usbipd-win/releases

同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:

1
+
$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool
+

打开wsl ubuntu终端使用命令:uname -r得到版本号,同时根据版本号使用管理员模式新建目录

screenshot_image.png

1
+
$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2
+

同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases

这里的版本就是你使用命令 uname -r 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下

然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):

1
+2
+3
+4
+
$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/
+
+$ cd /usr/src/5.15.90.1-microsoft-standard-WSL2/
+$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ && sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1
+

然后将内核的一些配置信息复制到当前文件夹下:

1
+2
+3
+
$ sudo cp /proc/config.gz config.gz
+$ sudo gunzip config.gz
+$ sudo mv config .config
+

接着我们执行menuconfig命令打开图形化菜单

1
+
$ sudo make menuconfig
+

进入如下路径:> Device Drivers > USB support

下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:

1
+2
+3
+4
+5
+6
+7
+
Device Drivers -> USB Support
+Device Drivers -> USB Support -> USB announce new devices
+Device Drivers -> USB Support -> USB Modem (CDC ACM) support
+Device Drivers -> USB Support -> USB/IP
+Device Drivers -> USB Support -> USB/IP -> VHCI HCD
+Device Drivers -> USB Serial Converter Support
+Device Drivers -> USB Serial Converter Support -> USB FTDI Single port Serial Driver
+

同时记得关闭 Device Drivers -> USB Support -> USB/IP -> Debug messages for USB/IP这一选项,否则调试信息会非常影响你的使用体验

另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译

1
+
$ sudo make -j8 
+

内核编译期间发生报错:

screenshot_image.png

这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:

1
+2
+3
+
$ sudo apt install dwarves
+
+$ sudo make -j8 && sudo make modules_install -j8 && sudo make install -j8
+

发现又产生了报错:

screenshot_image.png

查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题

1
+2
+3
+
$ sudo vi .config
+
+# 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`
+

安装内核时发生报错:

screenshot_image.png

解决方式有两种:

  • 1.可以选择在.config中禁用宏CONFIG_X86_X32
  • 2.找到合适的binutils版本使其能够编译

我选择的是第一种,根据我在网上找到的说法是:

1
+2
+3
+
# 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。
+
+# 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。
+

所以我选择禁用宏CONFIG_X86_X32,之后继续执行命令:

1
+2
+
$ sudo make modules_install -j8
+$ sudo make install -j8
+

screenshot_image.png

之后就可以选择编译 USBIP 工具了:

1
+2
+3
+4
+
$ cd tools/usb/usbip
+$ sudo ./autogen.sh
+$ sudo ./configure
+$ sudo make install -j8
+

复制工具库位置,以便 usbip 工具可以获取到:

1
+
$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0
+

安装 usb.ids 以便显示 USB 设备的名称:

1
+
$ sudo apt-get install hwdata
+

重启WSL:

1
+
$ wsl --shutdown
+

下面进行测试是否成功: +打开powershell:

1
+
$ usbipd wsl list
+

假设我们需要在wsl使用的 usb 设备为 ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3),设备id为 0483:374b

我们使用命令附加设备到 wsl2 中

1
+
$ usbipd wsl attach --hardware-id "0483:374b"
+

screenshot_image.png

此时我们打开一个 wsl 终端,使用命令 lsusb 即可看到附加到 wsl 的设备

screenshot_image.png

然后我们再次回到 powershell ,执行 usbipd wsl list命令,可以看到此时的 usb 设备已经成功添加到 wsl 了

screenshot_image.png

+Licensed under CC BY-NC-SA 4.0
+Last updated on Oct 26, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a.jpg" new file mode 100644 index 000000000..5b663600d Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a_hu6cc81a9902269324bd2156ee8382941d_21092_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a_hu6cc81a9902269324bd2156ee8382941d_21092_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..53426d4b4 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.8a302a1da0b8e2e7dbad3c0236a28b5a_hu6cc81a9902269324bd2156ee8382941d_21092_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.jpg" new file mode 100644 index 000000000..5b663600d Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..ab6bf9d0a Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..8b04da976 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..a70fd58ac Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/cover_hu6cc81a9902269324bd2156ee8382941d_21092_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/index.html" new file mode 100644 index 000000000..d62fdee8d --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\345\246\202\344\275\225\350\256\251\344\275\240\347\232\204\347\273\210\347\253\257\345\256\236\347\216\260\350\207\252\345\212\250\350\241\245\351\275\220\345\216\206\345\217\262\345\233\236\346\272\257/index.html" @@ -0,0 +1,58 @@ +【经验分享】如何让你的终端实现自动补齐、历史回溯 +
Featured image of post 【经验分享】如何让你的终端实现自动补齐、历史回溯

【经验分享】如何让你的终端实现自动补齐、历史回溯

如何让你的终端实现自动补齐、历史回溯等功能,提升你的开发效率

+
+

Linux下配置

在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:

步骤 1: 安装 zsh

确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:

1
+
sudo apt-get install zsh
+

步骤 2: 安装 oh-my-zsh

在终端中运行以下命令来安装 oh-my-zsh:

1
+
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+

或者,如果你没有安装 curl,可以使用 wget

1
+
sh -c "$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)"
+

步骤 3: 更改主题

  1. 打开 ~/.zshrc 文件以编辑它:

    1
    +
    nano ~/.zshrc
    +
  2. 找到 ZSH_THEME 行并更改主题。你可以在 oh-my-zsh 主题库中选择一个主题,例如:

    1
    +
    ZSH_THEME="agnoster"
    +
  3. 保存并关闭文件。

步骤 4: 启用历史回溯

oh-my-zsh 默认启用历史回溯。确保 ~/.zshrc 中没有明确禁用该功能的设置。检查是否存在以下行:

1
+
HIST_STAMPS="yyyy-mm-dd"
+

这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:

1
+
HIST_STAMPS=""
+

步骤 5: 重新启动 zsh 或打开新终端

在更改 ~/.zshrc 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。

1
+
source ~/.zshrc
+

现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 zsh 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。

Windwos下配置

在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 PSReadLine 模块,它提供了丰富的命令行编辑和历史记录功能。

以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:

  1. 安装 PSReadLine 模块: +打开 PowerShell 终端,并执行以下命令来安装 PSReadLine 模块:

    1
    +
    Install-Module -Name PSReadLine -Force -SkipPublisherCheck
    +
  2. 配置 PowerShell 用户配置文件: +执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):

    1
    +
    notepad $PROFILE
    +
  3. 在配置文件中添加以下行: +在打开的配置文件中,添加以下内容:

    1
    +2
    +3
    +4
    +
    Import-Module PSReadLine
    +
    +Set-PSReadLineOption -HistoryNoDuplicates:$false
    +Set-PSReadLineOption -EditMode Emacs
    +

    保存并关闭文件。

  4. 重新启动 PowerShell: +关闭当前的 PowerShell 终端,并重新打开一个新的终端。

  5. 使用历史记录搜索: +可以在 PowerShell 终端中使用 Ctrl + r 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。

+Licensed under CC BY-NC-SA 4.0
+Last updated on Feb 03, 2024 15:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985.jpg" new file mode 100644 index 000000000..9160d54a4 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..a30473195 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.eace736933e9605d8d3be6f8daba3985_hu4f94b71a165b962db7609fb23d2e6f56_29527_250x150_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.jpg" new file mode 100644 index 000000000..9160d54a4 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..c1754452e Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..8a14295e5 Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..4c6db423c Binary files /dev/null and "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/index.html" "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/index.html" new file mode 100644 index 000000000..23873dec4 --- /dev/null +++ "b/p/\347\273\217\351\252\214\345\210\206\344\272\253\346\241\245\346\216\245\347\275\221\347\273\234\346\227\240\346\263\225\350\201\224\347\275\221\345\274\200\345\217\221\346\235\277\346\214\202\350\275\275\346\240\271\346\226\207\344\273\266\347\263\273\347\273\237\351\227\256\351\242\230\350\247\243\345\206\263/index.html" @@ -0,0 +1,95 @@ +总结:开发板挂载根文件系统遇到的一些问题 +
Featured image of post 总结:开发板挂载根文件系统遇到的一些问题

总结:开发板挂载根文件系统遇到的一些问题

桥接网络、开发板端测

+
+

一、桥接网络

1、简介

是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址

注意避坑:

如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。

2、解决办法:

<1>选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。

image-20230424131854375

image-20230424131957782

<2>无线网卡连接

考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)

如下配置:

  • 主机配置

首先电脑win+R,输入cmd进入终端,然后输入命令:ipconfig,找到自己的热点网络信息

image-20230424132028276

image-20230424132041431

image-20230424132117501

  • 虚拟机配置

image-20230424132214739

image-20230424132233318

1
+
ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces
+

image-20230424132250210

1
+2
+3
+
保存退出后,再次输入命令:
+首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡)
+然后启用网卡:ifup eth0
+

二、开发板端测试:

以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客

【Linux系统开发】x210开发板根目录文件系统构建

我们打开secureCRT:

开机先ping下虚拟机网络:ping '虚拟机IP'

注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
方法一:打开命令:sudo gedit /etc/NetworkManager/nm-system-settings.conf
+
+出现文件内容:
+
+# This file is installed into /etc/NetworkManager, and is loaded by
+# NetworkManager by default.  To override, specify: '--config file'
+# during NM startup.  This can be done by appending to DAEMON_OPTS in
+# the file:
+#
+# /etc/default/NetworkManager
+#
+
+[main]
+plugins=ifupdown,keyfile
+
+[ifupdown]
+managed=true
+
+(这里false改成true
+
1
+2
+3
+4
+5
+6
+7
+
方法二:虚拟机重置网卡
+
+sudo /etc/init.d/networking restart
+sudo /etc/init.d/networking start
+
+ifdown eth0
+ifup eth0
+

当开发板ping通虚拟机后,我们在secureCRT控制台输入reset命令重启开发板

image-20230424132308595

这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应

image-20230424132323723

解决:

1
+2
+3
+4
+5
+
mount -t nfs -o nolock '开发板ipaddr ip':/root/rootfs/x210_rootfs   //再次重新挂载根文件系统
+
+//NFC网络重启
+/etc/init.d/nfs-kernel-server restart 
+sudo /etc/init.d/networking start
+

image-20230424132335917

问题解决!

+Licensed under CC BY-NC-SA 4.0
+Last updated on Mar 30, 2022 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover.jpg" "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover.jpg" new file mode 100644 index 000000000..e61781421 Binary files /dev/null and "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover.jpg" differ diff --git "a/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_120x120_fill_q75_box_smart1.jpg" "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..3b4904ad0 Binary files /dev/null and "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_1600x0_resize_q75_box.jpg" "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..6f60e405e Binary files /dev/null and "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_800x0_resize_q75_box.jpg" "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..4be06c41f Binary files /dev/null and "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/cover_hua119e4204b5ed27e667ee608d4609605_260211_800x0_resize_q75_box.jpg" differ diff --git "a/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/index.html" "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/index.html" new file mode 100644 index 000000000..b3d665c64 --- /dev/null +++ "b/p/\347\275\221\347\273\234\347\274\226\347\250\213osi\344\270\203\345\261\202\346\250\241\345\236\213tcpip\345\233\233\345\261\202\346\250\241\345\236\213/index.html" @@ -0,0 +1,37 @@ +【网络编程】OSI七层模型&TCPIP四层模型 +
Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型

【网络编程】OSI七层模型&TCPIP四层模型

在网络通信中,OSI七层模型和TCP/IP四层模型都是常用的网络协议模型。本篇文章将从OSI七层模型和TCP/IP四层模型的概念出发,介绍它们各自的层级结构、关键点和特点。

+
+

OSI七层模型

七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。

1.物理层

建立、维护、断开物理连接。(由底层网络定义协议)

机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。

应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。

2.数据链路层

建立逻辑连接、进行硬件地址寻址、差错校验等功能。(由底层网络定义协议)

将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)

3.网络层

进行逻辑地址寻址,实现不同网络之间的路径选择。

控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)

4.传输层

定义传输数据的协议端口号,以及流控和差错校验。 +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层

5.会话层

建立、管理、终止会话。(在五层模型里面已经合并到了应用层)

不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)

6.表示层

数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)

信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)

7.应用层

网络服务与最终用户的一个接口

各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)


TCP/IP 四层模型

TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

20201028134158932

TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示

1.应用层

应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。

  • 应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次
  • 对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议
  • 应用层还能加密、解密、格式化数据
  • 应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源

2.传输层

作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用

3.网络层

网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能

4.网络接口层

在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路

+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 10, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git "a/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover.jpg" "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover.jpg" new file mode 100644 index 000000000..607f81a98 Binary files /dev/null and "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover.jpg" differ diff --git "a/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_120x120_fill_q75_box_smart1.jpg" "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_120x120_fill_q75_box_smart1.jpg" new file mode 100644 index 000000000..bf3f77312 Binary files /dev/null and "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_120x120_fill_q75_box_smart1.jpg" differ diff --git "a/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_1600x0_resize_q75_box.jpg" "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_1600x0_resize_q75_box.jpg" new file mode 100644 index 000000000..e6c4cd758 Binary files /dev/null and "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_1600x0_resize_q75_box.jpg" differ diff --git "a/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_800x0_resize_q75_box.jpg" "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_800x0_resize_q75_box.jpg" new file mode 100644 index 000000000..58f802bd0 Binary files /dev/null and "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_800x0_resize_q75_box.jpg" differ diff --git "a/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/index.html" "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/index.html" new file mode 100644 index 000000000..15abbd5ba --- /dev/null +++ "b/p/\350\265\204\350\256\257\346\261\207\346\200\273\344\270\200\344\272\233\345\265\214\345\205\245\345\274\217\347\233\270\345\205\263\347\232\204\345\205\254\345\217\270/index.html" @@ -0,0 +1,25 @@ +【资讯】汇总一些嵌入式相关的公司 +
Featured image of post 【资讯】汇总一些嵌入式相关的公司

【资讯】汇总一些嵌入式相关的公司

汇总一些嵌入式相关的公司

+
+

来源:https://zhuanlan.zhihu.com/p/585079427

1.芯片行业

目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。

代表性公司:

(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等

(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等

2.人工智能相关行业

(1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。

(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等

3.消费电子行业

消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等

4.传统汽车行业

传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等

5.国企和军工

国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。

6.传统电子电器类

这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等

7.网络及通信设备

主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等

+Licensed under CC BY-NC-SA 4.0
+Last updated on Apr 03, 2023 00:00 UTC
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git a/page/1/index.html b/page/1/index.html new file mode 100644 index 000000000..72a23df04 --- /dev/null +++ b/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/ + \ No newline at end of file diff --git a/page/10/index.html b/page/10/index.html new file mode 100644 index 000000000..7d0cb659d --- /dev/null +++ b/page/10/index.html @@ -0,0 +1,71 @@ +Pager 10 - kurisaW +
Featured image of post CPK-RA6M4智慧门禁系统教学

CPK-RA6M4智慧门禁系统教学

本视频秉持着学习开放的思想,在RT-Thread夏令营经历的这几周时间,自己也是结合所学知识开发出一款智慧门禁系统,而为了大家更好的学习交流,本次将以视频录制加源码开源的方式供大家学习参考。

+
+
\ No newline at end of file diff --git a/page/11/index.html b/page/11/index.html new file mode 100644 index 000000000..5b0c31b26 --- /dev/null +++ b/page/11/index.html @@ -0,0 +1,71 @@ +Pager 11 - kurisaW +
Featured image of post 线程间同步 信号量

线程间同步 信号量

信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。

+
+
Featured image of post 线程管理

线程管理

在 RT-Thread 中,线程是实现任务的载体,它是 RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。

+
+
Featured image of post I2C(内核学习)

I2C(内核学习)

I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。

+
+
\ No newline at end of file diff --git a/page/12/index.html b/page/12/index.html new file mode 100644 index 000000000..6d400d7d5 --- /dev/null +++ b/page/12/index.html @@ -0,0 +1,70 @@ +Pager 12 - kurisaW +
Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)

RT-Thread Studio使用 2.内核实战篇(线程)

在 RT-Thread 中,线程是实现任务的载体,它是 RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。

+
+
Featured image of post x11vnc安装与配置

x11vnc安装与配置

最近学校在做ros使用树莓派做一个路径规划,但是一般的vncserver无法使用rviz可视化工具,所以选择了x11vnc这款工具。

+
+
\ No newline at end of file diff --git a/page/13/index.html b/page/13/index.html new file mode 100644 index 000000000..dc5032470 --- /dev/null +++ b/page/13/index.html @@ -0,0 +1,69 @@ +Pager 13 - kurisaW +
Featured image of post env工具学习

env工具学习

Env 是 RT-Thread 推出的开发辅助工具,包括配置器和包管理器。开发者可以使用 Env 工具对 RT-Thread 内核和组件的功能进行配置,对组件进行自由裁剪,对线上软件包进行管理,使得系统以搭积木的方式进行构建,简单方便。

+
+
Featured image of post 多线程技术学习(基于Linux)

多线程技术学习(基于Linux)

Linux多线程概念、inux线程实现、线程同步的方法、线程的互斥、互斥PK信号量、信号量操作、互斥操作、条件变量

+
+
\ No newline at end of file diff --git a/page/14/index.html b/page/14/index.html new file mode 100644 index 000000000..2c1766baf --- /dev/null +++ b/page/14/index.html @@ -0,0 +1,68 @@ +Pager 14 - kurisaW +
Featured image of post 信号量及PV操作详解

信号量及PV操作详解

无论是大部分的教材上的信号量,还是博客中的信号量,基本上解说都是类似下面这种,给出几个不同的信号量种类然后加一点说明,完全不能理解信号量的PV操作。本文基于此对信号量进行详细叙述,希望能对你有所帮助!

+
+
Featured image of post 进程上下文和线程上下文

进程上下文和线程上下文

在操作系统的学习中,我们经常会遇到诸如进程、线程、进程上下文和线程上下文等语义,但具体是什么意思,相信大家也时常被绕晕。今天就具体讲解一下关于进程、线程及一些相关术语的解释。

+
+
Featured image of post C素养提升-函数专题

C素养提升-函数专题

在c语言中,函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。

+
+
Featured image of post C素养提升-指针专题

C素养提升-指针专题

在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。

+
+
\ No newline at end of file diff --git a/page/2/index.html b/page/2/index.html new file mode 100644 index 000000000..98db44deb --- /dev/null +++ b/page/2/index.html @@ -0,0 +1,69 @@ +Pager 2 - kurisaW +
Featured image of post 【Matter】CHIP设备层设计笔记

【Matter】CHIP设备层设计笔记

本文档包含与 CHIP 设备层 ( `src/platform`) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方。

+
+
\ No newline at end of file diff --git a/page/3/index.html b/page/3/index.html new file mode 100644 index 000000000..b3be3e66c --- /dev/null +++ b/page/3/index.html @@ -0,0 +1,70 @@ +Pager 3 - kurisaW +
Featured image of post 【Matter】Matter学习笔记1

【Matter】Matter学习笔记1

Matter 作为一个应用级的协议,向下屏蔽了设备制造商的生态和系统,让各种智能家居设备之间能相互通信。

+
+
Featured image of post 【Matter】Nordic-Mattter开发大纲

【Matter】Nordic-Mattter开发大纲

这部分仅作为开发大纲,后面会出一系列系统教程,以 Matter over Thread:在一台设备上配置边界路由器和控制器 为例。

+
+
\ No newline at end of file diff --git a/page/4/index.html b/page/4/index.html new file mode 100644 index 000000000..ee0946b6a --- /dev/null +++ b/page/4/index.html @@ -0,0 +1,71 @@ +Pager 4 - kurisaW +
\ No newline at end of file diff --git a/page/5/index.html b/page/5/index.html new file mode 100644 index 000000000..ef92660c0 --- /dev/null +++ b/page/5/index.html @@ -0,0 +1,71 @@ +Pager 5 - kurisaW +
Featured image of post Github同步Gitee镜像仓库自动化脚本

Github同步Gitee镜像仓库自动化脚本

在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。

+
+
Featured image of post Wireshark网络抓包教程

Wireshark网络抓包教程

Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。

+
+
Featured image of post RT-Thread内核宏定义详解(rtdef.h)

RT-Thread内核宏定义详解(rtdef.h)

RT-Thread是一款轻量级的实时操作系统,它在嵌入式系统领域得到了广泛应用。其中,rtdef.h 头文件定义了RT-Thread操作系统中很多重要的宏定义,这些宏定义提供了对操作系统内部数据结构和常用函数的封装和定义。通过了解和掌握这些宏定义,可以更方便地编写和调试 RT-Thread 应用程序,从而提高程序的可靠性和健壮性。本文将详细介绍 rtdef.h 头文件中部分宏定义的作用、用法和注意事项,帮助读者深入理解 RT-Thread 内核,在开发嵌入式应用时更加得心应手。

+
+
Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建

【HarmonyOS】小熊派鸿蒙系统搭建

BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。

+
+
\ No newline at end of file diff --git a/page/6/index.html b/page/6/index.html new file mode 100644 index 000000000..cb9b5bf78 --- /dev/null +++ b/page/6/index.html @@ -0,0 +1,71 @@ +Pager 6 - kurisaW +
Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务

【Linux系统开发】Ubuntu配置SFTP服务

SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。

+
+
Featured image of post 【Git版本控制】Git命令详解

【Git版本控制】Git命令详解

Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 回撤这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而版本管理工具能记录每次的修改,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。

+
+
\ No newline at end of file diff --git a/page/7/index.html b/page/7/index.html new file mode 100644 index 000000000..ea73a6334 --- /dev/null +++ b/page/7/index.html @@ -0,0 +1,71 @@ +Pager 7 - kurisaW +
\ No newline at end of file diff --git a/page/8/index.html b/page/8/index.html new file mode 100644 index 000000000..68b027a26 --- /dev/null +++ b/page/8/index.html @@ -0,0 +1,71 @@ +Pager 8 - kurisaW +
Featured image of post 【NXP】LPC55S69初上手

【NXP】LPC55S69初上手

前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。

+
+
\ No newline at end of file diff --git a/page/9/index.html b/page/9/index.html new file mode 100644 index 000000000..6461dd163 --- /dev/null +++ b/page/9/index.html @@ -0,0 +1,71 @@ +Pager 9 - kurisaW +
\ No newline at end of file diff --git a/page/index.html b/page/index.html new file mode 100644 index 000000000..0821217f5 --- /dev/null +++ b/page/index.html @@ -0,0 +1,56 @@ +Pages +

Section

7 pages

Pages

\ No newline at end of file diff --git a/page/index.xml b/page/index.xml new file mode 100644 index 000000000..c86412d02 --- /dev/null +++ b/page/index.xml @@ -0,0 +1,281 @@ +Pages on kurisaWhttps://kurisaw.github.io/page/Recent content in Pages on kurisaWHugo -- gohugo.ioenSun, 06 Mar 2022 00:00:00 +0000Archiveshttps://kurisaw.github.io/archives/Sun, 06 Mar 2022 00:00:00 +0000https://kurisaw.github.io/archives/Abouthttps://kurisaw.github.io/about/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/about/<h2 id="hi-there">Hi there!👋 +</h2><p>I&rsquo;m KurisaW,or you can call me yifang.</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="l">🔭 Now I am a junior student ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">🌱 I’m currently learning RT-Thread、linux、ROS ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">👯 I’m looking to collaborate on Embedded or neural network ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">🤔 I&#39;m looking forward to sharing my experience and learning to help some beginners get through the rookie phase faster ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">💬 Ask me about Linux、Embedded ...</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">😊 I will be happy to discuss technology and knowledge with you and look forward to your visit!</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>Contact me:</code></p> +<ul> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> +<p><code>You can also choose to get in touch with me by adding wechat!</code></p> +<p><img src="https://user-images.githubusercontent.com/98592772/218299666-0cb3baea-a528-4216-99bd-06806149aaa9.png" +loading="lazy" +alt="Wechat" +></p>Documentshttps://kurisaw.github.io/documents/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/documents/<h1 id="说明">说明 +</h1><p>这里我存放了一些个人搜集的文档资源,支持PDF在线查看,同时也欢迎各位在评论区留下相关资源链接!</p> +<p>由于构建方式使用的是PDF.js插件,是为html5实现的在线预览pdf框架,所以使用的前提是浏览器要支持html5。该插件不需要任何本地支持,对浏览器的兼容性也比较好(低版本的IE浏览器不支持)。</p> +<p>配置仓库入口:<a class="link" href="https://github.com/kurisaW/Npdf" target="_blank" rel="noopener" +>https://github.com/kurisaW/Npdf</a></p> +<p><strong>注:目前本博客的pdf资源已部分上传至infinityfree服务器,较之pdf.js有更快响应速度,后续考虑国内CDN加速,当然想要学习和了解pdf.js的构建方式也可参考此仓库<a class="link" href="https://github.com/kurisaW/Npdf" target="_blank" rel="noopener" +>Npdf</a>;由于部分pdf文件较大,反应速度慢属于正常现象。</strong></p> +<h1 id="目前上传的pdf资源如下">目前上传的PDF资源如下: +</h1><h3 id="精品专栏">精品专栏 +</h3><ul> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/05/30%e5%a4%a9%e8%87%aa%e5%88%b6%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f-%e5%9b%be%e7%81%b5%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b8%9b%e4%b9%a6.pdf" target="_blank" rel="noopener" +>30天自制操作系统-图灵程序设计丛书</a></li> +</ul> +<h3 id="c语言专栏">C语言专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=GCC.chinese-manual.pdf" target="_blank" rel="noopener" +>GCC.chinese-manual.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e9%99%b7%e9%98%b1%e4%b8%8e%e7%bc%ba%e9%99%b7.pdf" target="_blank" rel="noopener" +>C陷阱与缺陷.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e9%9b%86%ef%bc%88%e9%97%ae%e9%a2%98%e6%8f%90%e9%ab%98%e7%89%88%ef%bc%89.pdf" target="_blank" rel="noopener" +>C语言常见问题集(问题提高版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e5%87%bd%e6%95%b0%e5%a4%a7%e5%85%a8.pdf" target="_blank" rel="noopener" +>C语言函数大全.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e6%b7%b1%e5%ba%a6%e8%a7%a3%e5%89%96-%e8%a7%a3%e5%bc%80%e7%a8%8b%e5%ba%8f%e5%91%98%e9%9d%a2%e8%af%95%e7%ac%94%e8%af%95%e7%9a%84%e7%a7%98%e5%af%86.pdf" target="_blank" rel="noopener" +>C语言深度解剖-解开程序员面试笔试的秘密.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=C%e8%af%ad%e8%a8%80%e6%8c%87%e9%92%88%e7%bb%8f%e9%aa%8c%e6%80%bb%e7%bb%93.pdf" target="_blank" rel="noopener" +>C语言指针经验总结.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/C%e8%af%ad%e8%a8%80%e8%a7%84%e8%8c%83%e6%a0%87%e5%87%86-C99.pdf" target="_blank" rel="noopener" +>C语言规范标准-C99.pdf</a></li> +</ul> +<h3 id="c专栏">C++专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%bb%8e%e6%94%be%e5%bc%83C%e8%af%ad%e8%a8%80%e5%88%b0%e4%bd%bf%e7%94%a8CPlusPlus%e5%88%b7%e7%ae%97%e6%b3%95%e7%9a%84%e7%ae%80%e6%98%8e%e6%95%99%e7%a8%8b.pdf" target="_blank" rel="noopener" +>从放弃C语言到使用CPlusPlus刷算法的简明教程.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Google.CPlusPlus-Style-Guide.pdf" target="_blank" rel="noopener" +>Google.CPlusPlus-Style-Guide.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e7%bc%96%e7%a8%8b%e8%a7%84%e8%8c%83-101%e6%9d%a1%e8%a7%84%e5%88%99%e5%87%86%e5%88%99%e4%b8%8e%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5.pdf" target="_blank" rel="noopener" +>CPlusPlus编程规范-101条规则准则与最佳实践.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e6%a0%87%e5%87%86%e7%a8%8b%e5%ba%8f%e5%ba%93.pdf" target="_blank" rel="noopener" +>CPlusPlus标准程序库.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e5%af%b9%e8%b1%a1%e6%a8%a1%e5%9e%8b.pdf" target="_blank" rel="noopener" +>CPlusPlus对象模型.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Effective_STL%e4%b8%ad%e6%96%87%e7%89%88.pdf" target="_blank" rel="noopener" +>Effective_STL中文版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=STL%e6%ba%90%e7%a0%81%e5%89%96%e6%9e%90.pdf" target="_blank" rel="noopener" +>STL源码剖析.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%b7%9f%e6%88%91%e4%b8%80%e8%b5%b7%e5%86%99makefile.pdf" target="_blank" rel="noopener" +>跟我一起写makefile.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%ba%a6%e6%8e%a2%e7%b4%a2CPlusPlus%e5%af%b9%e8%b1%a1%e6%a8%a1%e5%9e%8b.pdf" target="_blank" rel="noopener" +>深度探索CPlusPlus对象模型.pdf</a></li> +</ul> +<h3 id="linux专栏">Linux专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux-series-summary-manual.pdf" target="_blank" rel="noopener" +>Linux-series-summary-manual.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux_UNIX%e7%b3%bb%e7%bb%9f%e7%bc%96%e7%a8%8b%e6%89%8b%e5%86%8c%ef%bc%88%e4%b8%8a%ef%bc%89.pdf" target="_blank" rel="noopener" +>Linux_UNIX系统编程手册(上).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux_UNIX%e7%b3%bb%e7%bb%9f%e7%bc%96%e7%a8%8b%e6%89%8b%e5%86%8c%ef%bc%88%e4%b8%8b%ef%bc%89.pdf" target="_blank" rel="noopener" +>Linux_UNIX系统编程手册(下).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux%e5%86%85%e6%a0%b8%e8%ae%be%e8%ae%a1%e4%b8%8e%e5%ae%9e%e7%8e%b0.pdf" target="_blank" rel="noopener" +>Linux内核设计与实现.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=linux%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4%e5%a4%a7%e5%85%a8.pdf" target="_blank" rel="noopener" +>linux常用命令大全.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=linux%e5%86%85%e6%a0%b8%e5%ae%8c%e5%85%a8%e6%b3%a8%e9%87%8a.pdf" target="_blank" rel="noopener" +>linux内核完全注释.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Linux%e7%b3%bb%e7%bb%9f%e5%91%bd%e4%bb%a4%e5%8f%8ashell%e8%84%9a%e6%9c%ac%e5%ae%9e%e8%b7%b5%e6%8c%87%e5%8d%97linuxunix%e6%8a%80%e6%9c%af%e4%b8%9b%e4%b9%a6.pdf" target="_blank" rel="noopener" +>Linux系统命令及shell脚本实践指南linuxunix技术丛书.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e9%b8%9f%e5%93%a5%e7%9a%84LINUX%e7%a7%81%e6%88%bf%e8%8f%9c_%e5%9f%ba%e7%a1%80%e5%ad%a6%e4%b9%a0%e7%af%87%28%e7%ac%ac%e4%b8%89%e7%89%88%29.pdf" target="_blank" rel="noopener" +>鸟哥的LINUX私房菜_基础学习篇(第三版).pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e9%b8%9f%e5%93%a5%e7%9a%84Linux%e7%a7%81%e6%88%bf%e8%8f%9c%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%9e%b6%e8%ae%be%e7%af%87%28%e7%ac%ac%e4%b8%89%e7%89%88%29.pdf" target="_blank" rel="noopener" +>鸟哥的Linux私房菜服务器架设篇(第三版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%85%a5Linux%e5%86%85%e6%a0%b8%e6%9e%b6%e6%9e%84%28%e5%9b%be%e7%81%b5%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b8%9b%e4%b9%a6%c2%b7LinuxUNIX%e7%b3%bb%e5%88%97%29.pdf" target="_blank" rel="noopener" +>深入Linux内核架构(图灵程序设计丛书·LinuxUNIX系列).pdf</a></li> +</ul> +<h3 id="git专题">Git专题 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Git%e5%8f%82%e8%80%83%e6%89%8b%e5%86%8c-%e6%96%b0.pdf" target="_blank" rel="noopener" +>Git参考手册-新.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=Git%e6%9d%83%e5%a8%81%e6%8c%87%e5%8d%97.pdf" target="_blank" rel="noopener" +>Git权威指南.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%bb%8e0%e5%bc%80%e5%a7%8b%e5%ad%a6%e4%b9%a0GitHub%e7%b3%bb%e5%88%97.pdf" target="_blank" rel="noopener" +>从0开始学习GitHub系列.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%b8%93%e4%b8%9agit%e4%b8%ad%e6%96%87.pdf" target="_blank" rel="noopener" +>专业git中文.pdf</a></li> +</ul> +<h3 id="笔试面试专题">笔试面试专题 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e9%9d%a2%e7%bb%8f%e6%80%bb%e7%bb%93.pdf" target="_blank" rel="noopener" +>CPlusPlus面经总结.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=CPlusPlus%e7%89%9b%e5%ae%a2%e5%a4%a7%e4%bd%ac%e6%80%bb%e7%bb%93%e9%9d%a2%e8%af%95%e7%bb%8f%e9%aa%8c.pdf" target="_blank" rel="noopener" +>CPlusPlus牛客大佬总结面试经验.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e7%a8%8b%e5%ba%8f%e5%91%98%e9%9d%a2%e8%af%95%e5%ae%9d%e5%85%b8.pdf" target="_blank" rel="noopener" +>程序员面试宝典.pdf</a></li> +</ul> +<h3 id="操作系统专栏">操作系统专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e6%a6%82%e5%bf%b5.pdf" target="_blank" rel="noopener" +>操作系统概念.pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%b3%bb%e7%bb%9f%e8%a6%81%e7%b4%a0-%e4%bb%8e%e9%9b%b6%e5%bc%80%e5%a7%8b%e6%9e%84%e5%bb%ba%e7%8e%b0%e4%bb%a3%e8%ae%a1%e7%ae%97%e6%9c%ba.pdf" target="_blank" rel="noopener" +>计算机系统要素-从零开始构建现代计算机.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%b3%bb%e7%bb%9f-%e7%ac%ac3%e7%89%88.pdf" target="_blank" rel="noopener" +>深入理解计算机系统-第3版.pdf</a> *</li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e8%87%aa%e5%b7%b1%e5%8a%a8%e6%89%8b%e5%86%99%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f.pdf" target="_blank" rel="noopener" +>自己动手写操作系统.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=RTThread_manual.zh.pdf" target="_blank" rel="noopener" +>RTThread_manual.zh.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=RT-Thread%e7%bc%96%e7%a8%8b%e6%8c%87%e5%8d%97.pdf" target="_blank" rel="noopener" +>RT-Thread编程指南.pdf</a></li> +</ul> +<h3 id="数据结构与算法专栏">数据结构与算法专栏 +</h3><ul> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e7%bc%96%e7%a8%8b%e4%b9%8b%e7%be%8e-%e5%ae%8c%e6%95%b4%e7%89%88.pdf" target="_blank" rel="noopener" +>编程之美-完整版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e5%89%91%e6%8c%87Offer.pdf" target="_blank" rel="noopener" +>剑指offer.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e5%89%91%e6%8c%87offer_%e5%90%8d%e4%bc%81%e9%9d%a2%e8%af%95%e5%ae%98%e7%b2%be%e8%ae%b2%e5%85%b8%e5%9e%8b%e7%bc%96%e7%a8%8b%e9%a2%98-%e7%ac%ac2%e7%89%88.pdf" target="_blank" rel="noopener" +>剑指offer_名企面试官精讲典型编程题-第2版.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e4%b8%8e%e7%ae%97%e6%b3%95%e5%88%86%e6%9e%90CPlusPlus%e6%8f%8f%e8%bf%b0.pdf" target="_blank" rel="noopener" +>数据结构与算法分析CPlusPlus描述.pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e4%b8%a5%e8%94%9a%e6%95%8f-%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e9%a2%98%e9%9b%86%28C%e8%af%ad%e8%a8%80%e7%89%88%29.pdf" target="_blank" rel="noopener" +>严蔚敏-数据结构题集(C语言版).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e8%b4%aa%e5%bf%83%e7%ae%97%e6%b3%95%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」贪心算法专题精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e5%9b%9e%e6%ba%af%e7%ae%97%e6%b3%95%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」回溯算法精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e5%8a%a8%e6%80%81%e8%a7%84%e5%88%92%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」动态规划专题精讲(v2.0).pdf</a></li> +<li><a class="link" href="https://kurisaw.github.io/Npdf//web/viewer.html?file=%e3%80%8c%e4%bb%a3%e7%a0%81%e9%9a%8f%e6%83%b3%e5%bd%95%e3%80%8d%e4%ba%8c%e5%8f%89%e6%a0%91%e4%b8%93%e9%a2%98%e7%b2%be%e8%ae%b2%ef%bc%88v2.0%ef%bc%89.pdf" target="_blank" rel="noopener" +>「代码随想录」二叉树专题精讲(v2.0).pdf</a></li> +</ul> +<h3 id="历年软考嵌入式系统设计师真题及答案">历年软考嵌入式系统设计师真题及答案 +</h3><ul> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e6%95%99%e7%a8%8b.pdf" target="_blank" rel="noopener" +>嵌入式系统设计师教程.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师上午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2006%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2006年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师上午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2007%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2007年下半年嵌入式系统设计师下午试题及答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e5%8d%b7.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师上午试卷.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师上午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2008%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2008年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2009%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2009下半年嵌入式系统设计师上午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2009%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2009下半年嵌入式系统设计师下午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师上午试题及答案解析.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师下午试题.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2010%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2010年下半年嵌入式系统设计师下午试题答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2011%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e9%a2%98%e4%b8%8e%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2011年下半年嵌入式系统设计师上午试题与答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2011%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%88%86%e6%9e%90%e4%b8%8e%e8%a7%a3%e7%ad%94.pdf" target="_blank" rel="noopener" +>2011年下半年嵌入式系统设计师下午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2012-2013%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88.pdf" target="_blank" rel="noopener" +>2012-2013年下半年嵌入式系统设计师上午+下午试题及答案.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2014%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e8%af%95%e5%8d%b7%e7%bb%bc%e5%90%88%e7%9f%a5%e8%af%86.pdf" target="_blank" rel="noopener" +>2014年下半年嵌入式系统设计师上午试题分析与解答.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2015%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e7%9c%9f%e9%a2%98%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2015年下半年嵌入式系统设计师上午+下午真题答案+解析.pdf</a></li> +<li><a class="link" href="http://kurisaw-pdf-build.epizy.com/wp-content/uploads/2023/04/2016%e5%b9%b4%e4%b8%8b%e5%8d%8a%e5%b9%b4%e5%b5%8c%e5%85%a5%e5%bc%8f%e7%b3%bb%e7%bb%9f%e8%ae%be%e8%ae%a1%e5%b8%88%e4%b8%8a%e5%8d%88%e4%b8%8b%e5%8d%88%e7%9c%9f%e9%a2%98%e7%ad%94%e6%a1%88%e8%a7%a3%e6%9e%90.pdf" target="_blank" rel="noopener" +>2016年下半年嵌入式系统设计师上午+下午真题答案+解析.pdf</a></li> +</ul> +<h1 id="联系我">联系我 +</h1><p>如果你有相关资源想要集合到一个网站以便随时访问而又拘于时间问题没法搭建网站的话,可以与我取得联系,我将帮助你整理好资源,以此为你提供更加便利的阅读!</p> +<p>欢迎你的来访,期待与你有更好的合作!</p> +<p><a class="link" href="https://kurisaw.github.io/about/" target="_blank" rel="noopener" +>联系我请移步</a></p>Explorehttps://kurisaw.github.io/explore/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/explore/<p>If you have resources or tools that you recommend, you can contribute in the format below</p> +<p>This page&rsquo;s frontmatter:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">links</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Explore</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Here are some links to interesting and useful sites.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://kurisaw.github.io/explore/</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>image</code> field accepts both local and external images.</p>Linkshttps://kurisaw.github.io/links/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/links/<p>To use this feature, add <code>links</code> section to frontmatter.</p> +<p>This page&rsquo;s frontmatter:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">links</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">GitHub</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">GitHub is the world&#39;s largest software development platform.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.com</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">TypeScript</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">website</span><span class="p">:</span><span class="w"> </span><span class="l">https://www.typescriptlang.org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">ts-logo-128.jpg</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>image</code> field accepts both local and external images.</p>Quotehttps://kurisaw.github.io/quote/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/quote/<h1 id="读书-学习-去更远的地方">📑读书 学习 去更远的地方 +</h1><hr> +<div class="video-wrapper"> +<video +controls +src="./travel.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./travel.mp4">link to the video</a> instead. +</p> +</video> +</div> +<blockquote> +<p>每个人手上都拿着一张随时可能会输的牌,在人生中寻找补救的方法。</p><span class="cite"><span>― </span><span>星野道夫, </span><a href="https://kurisaw.github.io/quote/"><cite>《在漫长的旅途中》</cite></a></span></blockquote> +<blockquote> +<p>人只有在举棋不定,无从把握的时候才感到疲惫。只有去行动就能获得解放,哪怕做的不好也比无所作为强。</p><span class="cite"><span>― </span><span>斯蒂夫·茨威格, </span><a href="https://kurisaw.github.io/quote/"><cite>《创世纪》</cite></a></span></blockquote> +<blockquote> +<p>虚心佐我闪光 谦卑助我制胜 德行辅我压迫</p><span class="cite"><span>― </span><span>阿尔贝·加缪, </span><a href="https://kurisaw.github.io/quote/"><cite>《堕落》</cite></a></span></blockquote>Searchhttps://kurisaw.github.io/search/Mon, 01 Jan 0001 00:00:00 +0000https://kurisaw.github.io/search/ \ No newline at end of file diff --git a/page/page/1/index.html b/page/page/1/index.html new file mode 100644 index 000000000..baebd8645 --- /dev/null +++ b/page/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/page/ + \ No newline at end of file diff --git a/page/page/2/index.html b/page/page/2/index.html new file mode 100644 index 000000000..4686c901b --- /dev/null +++ b/page/page/2/index.html @@ -0,0 +1,56 @@ +Pages +

Section

7 pages

Pages

\ No newline at end of file diff --git a/post/index.html b/post/index.html new file mode 100644 index 000000000..915fa078d --- /dev/null +++ b/post/index.html @@ -0,0 +1,58 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/index.xml b/post/index.xml new file mode 100644 index 000000000..a717700c3 --- /dev/null +++ b/post/index.xml @@ -0,0 +1,28225 @@ +Posts on kurisaWhttps://kurisaw.github.io/post/Recent content in Posts on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduinohttps://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover.jpg" alt="Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino" /><h1 id="瑞萨hmi-board使用vscode开发rtduino结合ssd1306-oled">瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) +</h1><hr> +<h2 id="1准备工作">1.准备工作 +</h2><p>软件环境:</p> +<ul> +<li><a class="link" href="https://github.com/RT-Thread/rt-thread" target="_blank" rel="noopener" +> RT-Thread 主仓代码(需下载至本地)</a></li> +<li>vscode</li> +<li>rt-thread env</li> +</ul> +<p>硬件环境:</p> +<ul> +<li>RA6M3-HMI-Board 开发板</li> +<li>0.96寸 ssd1306 oled 显示屏</li> +</ul> +<h2 id="2工程配置">2.工程配置 +</h2><p>首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要我们提前安装好 ENV 环境,具体细节请参考 <a class="link" href="https://docs.rtduino.com/#/zh/beginner/env?id=env%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba" target="_blank" rel="noopener" +>Env编译环境搭建</a> 。</p> +<p>鼠标右键打开 ENV 工具后,使用 <strong>menuconfig</strong> 命令打开可视化菜单,勾选上 <strong>RTduino</strong> 的使能项,保存并退出</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251.png" +width="1086" +height="392" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123170636251" +class="gallery-image" +data-flex-grow="277" +data-flex-basis="664px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">RT-Thread Configuration +</span></span><span class="line"><span class="cl"> → Hardware Drivers Config +</span></span><span class="line"><span class="cl"> → Onboard Peripheral Drivers +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Compatible with Arduino Ecosystem <span class="o">(</span>RTduino<span class="o">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123171151275" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623.png" +width="1682" +height="768" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173108623" +class="gallery-image" +data-flex-grow="219" +data-flex-basis="525px" +></p> +<h2 id="3开始编译">3.开始编译 +</h2><p>打开 ENV ,同时执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons -j16 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173509831" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>在工程编译完成后会生成一个 <code>.elf</code>后缀的可执行文件,到这里工程的编译就顺利结束了。</p> +<h2 id="4vscode调试配置">4.vscode调试配置 +</h2><p>首先我们需要在 vscode 中安装 <code>Cortex-Debug</code> 插件,打开 vscode 扩展,搜索 <code>Cortex-Debug</code>并安装扩展:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123175244073" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接下来就是安装 <code>pyocd</code> 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 <code>create a launch.json file</code>:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889.png" +width="1385" +height="462" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123180230889" +class="gallery-image" +data-flex-grow="299" +data-flex-basis="719px" +></p> +<p>之后 vscode 会创建一份 <code>launch.json</code> 文件,我们需要替换文件内容为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// Use IntelliSense to learn about possible attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Hover to view descriptions of existing attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.2.0&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;configurations&#34;</span><span class="p">:</span> <span class="p">[</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;HMI-Board&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;cwd&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceFolder}&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;executable&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;request&#34;</span><span class="p">:</span> <span class="s2">&#34;launch&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;cortex-debug&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;runToEntryPoint&#34;</span><span class="p">:</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;targetId&#34;</span><span class="p">:</span> <span class="s2">&#34;R7FA6M3AH&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;servertype&#34;</span><span class="p">:</span> <span class="s2">&#34;pyocd&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;serverpath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/compile/sdk-debugger-pyocd/pyocd.bat&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;armToolchainPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;gdbPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<code>launch.json</code>文件中的部分参数需要根据具体位置配置</p> +<ul> +<li><code>serverpath</code>:这部分路径在前面所安装的 <code>sdk-debugger-pyocd</code>位置</li> +<li><code>armToolchainPath</code>:gcc 工具链,找不到位置的可以<a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>点击此处下载</a></li> +<li><code>gdbPath</code></li> +</ul> +<p>在完成上述配置后就可以点击 <code>F5</code> 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123183906784" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932.png" +width="815" +height="536" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184032932" +class="gallery-image" +data-flex-grow="152" +data-flex-basis="364px" +></p> +<p>到这里 RTduino 就已经成功运行在 RT-Thread 啦!</p> +<h2 id="5demo使用-rtduino-驱动-096寸-ssd1306-oled">5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled +</h2><p>在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过<code>RTduino</code>,并在<code>RT-Thread</code>中使用 <code>Arduino</code> 源码驱动一个 oled 屏幕。</p> +<p>我们接着回到 ENV 中,使用 <code>menuconfig</code>命令打开菜单,同时使用 <code>shift + /</code>打开搜索界面,并且输入:<code>ssd1306</code>关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 <code>Adafruit SSD1306</code>对应的 <code>2</code>选项,进入点击 <code>y</code> 使能:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184834403" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184930394" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p>这样我们就成功把 <code>Adafruit SSD1306</code> 示例库下载到本地了,同时还有一下依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453.png" +width="1720" +height="772" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123185120453" +class="gallery-image" +data-flex-grow="222" +data-flex-basis="534px" +></p> +<p>我们找到路径:<code>rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c</code>,可以看到该文件夹下有一个<code>ssd1306_128x64_i2c.ino</code>文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的<code>arduino_main.cpp</code>文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board<span class="se">\b</span>oard<span class="se">\r</span>tduino<span class="se">\a</span>rduino_main.cpp +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span><span class="lnt">267 +</span><span class="lnt">268 +</span><span class="lnt">269 +</span><span class="lnt">270 +</span><span class="lnt">271 +</span><span class="lnt">272 +</span><span class="lnt">273 +</span><span class="lnt">274 +</span><span class="lnt">275 +</span><span class="lnt">276 +</span><span class="lnt">277 +</span><span class="lnt">278 +</span><span class="lnt">279 +</span><span class="lnt">280 +</span><span class="lnt">281 +</span><span class="lnt">282 +</span><span class="lnt">283 +</span><span class="lnt">284 +</span><span class="lnt">285 +</span><span class="lnt">286 +</span><span class="lnt">287 +</span><span class="lnt">288 +</span><span class="lnt">289 +</span><span class="lnt">290 +</span><span class="lnt">291 +</span><span class="lnt">292 +</span><span class="lnt">293 +</span><span class="lnt">294 +</span><span class="lnt">295 +</span><span class="lnt">296 +</span><span class="lnt">297 +</span><span class="lnt">298 +</span><span class="lnt">299 +</span><span class="lnt">300 +</span><span class="lnt">301 +</span><span class="lnt">302 +</span><span class="lnt">303 +</span><span class="lnt">304 +</span><span class="lnt">305 +</span><span class="lnt">306 +</span><span class="lnt">307 +</span><span class="lnt">308 +</span><span class="lnt">309 +</span><span class="lnt">310 +</span><span class="lnt">311 +</span><span class="lnt">312 +</span><span class="lnt">313 +</span><span class="lnt">314 +</span><span class="lnt">315 +</span><span class="lnt">316 +</span><span class="lnt">317 +</span><span class="lnt">318 +</span><span class="lnt">319 +</span><span class="lnt">320 +</span><span class="lnt">321 +</span><span class="lnt">322 +</span><span class="lnt">323 +</span><span class="lnt">324 +</span><span class="lnt">325 +</span><span class="lnt">326 +</span><span class="lnt">327 +</span><span class="lnt">328 +</span><span class="lnt">329 +</span><span class="lnt">330 +</span><span class="lnt">331 +</span><span class="lnt">332 +</span><span class="lnt">333 +</span><span class="lnt">334 +</span><span class="lnt">335 +</span><span class="lnt">336 +</span><span class="lnt">337 +</span><span class="lnt">338 +</span><span class="lnt">339 +</span><span class="lnt">340 +</span><span class="lnt">341 +</span><span class="lnt">342 +</span><span class="lnt">343 +</span><span class="lnt">344 +</span><span class="lnt">345 +</span><span class="lnt">346 +</span><span class="lnt">347 +</span><span class="lnt">348 +</span><span class="lnt">349 +</span><span class="lnt">350 +</span><span class="lnt">351 +</span><span class="lnt">352 +</span><span class="lnt">353 +</span><span class="lnt">354 +</span><span class="lnt">355 +</span><span class="lnt">356 +</span><span class="lnt">357 +</span><span class="lnt">358 +</span><span class="lnt">359 +</span><span class="lnt">360 +</span><span class="lnt">361 +</span><span class="lnt">362 +</span><span class="lnt">363 +</span><span class="lnt">364 +</span><span class="lnt">365 +</span><span class="lnt">366 +</span><span class="lnt">367 +</span><span class="lnt">368 +</span><span class="lnt">369 +</span><span class="lnt">370 +</span><span class="lnt">371 +</span><span class="lnt">372 +</span><span class="lnt">373 +</span><span class="lnt">374 +</span><span class="lnt">375 +</span><span class="lnt">376 +</span><span class="lnt">377 +</span><span class="lnt">378 +</span><span class="lnt">379 +</span><span class="lnt">380 +</span><span class="lnt">381 +</span><span class="lnt">382 +</span><span class="lnt">383 +</span><span class="lnt">384 +</span><span class="lnt">385 +</span><span class="lnt">386 +</span><span class="lnt">387 +</span><span class="lnt">388 +</span><span class="lnt">389 +</span><span class="lnt">390 +</span><span class="lnt">391 +</span><span class="lnt">392 +</span><span class="lnt">393 +</span><span class="lnt">394 +</span><span class="lnt">395 +</span><span class="lnt">396 +</span><span class="lnt">397 +</span><span class="lnt">398 +</span><span class="lnt">399 +</span><span class="lnt">400 +</span><span class="lnt">401 +</span><span class="lnt">402 +</span><span class="lnt">403 +</span><span class="lnt">404 +</span><span class="lnt">405 +</span><span class="lnt">406 +</span><span class="lnt">407 +</span><span class="lnt">408 +</span><span class="lnt">409 +</span><span class="lnt">410 +</span><span class="lnt">411 +</span><span class="lnt">412 +</span><span class="lnt">413 +</span><span class="lnt">414 +</span><span class="lnt">415 +</span><span class="lnt">416 +</span><span class="lnt">417 +</span><span class="lnt">418 +</span><span class="lnt">419 +</span><span class="lnt">420 +</span><span class="lnt">421 +</span><span class="lnt">422 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/* +</span></span><span class="line"><span class="cl"> * Copyright <span class="o">(</span>c<span class="o">)</span> 2006-2023, RT-Thread Development Team +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * SPDX-License-Identifier: Apache-2.0 +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * Change Logs: +</span></span><span class="line"><span class="cl"> * Date Author Notes +</span></span><span class="line"><span class="cl"> * 2023-10-28 Wangyuqiang first version +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Arduino.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;SPI.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Wire.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_GFX.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_SSD1306.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_WIDTH 128 // OLED display width, in pixels</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_HEIGHT 64 // OLED display height, in pixels</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// Declaration <span class="k">for</span> an SSD1306 display connected to I2C <span class="o">(</span>SDA, SCL pins<span class="o">)</span> +</span></span><span class="line"><span class="cl">// The pins <span class="k">for</span> I2C are defined by the Wire-library. +</span></span><span class="line"><span class="cl">// On an arduino UNO: A4<span class="o">(</span>SDA<span class="o">)</span>, A5<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino MEGA 2560: 20<span class="o">(</span>SDA<span class="o">)</span>, 21<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino LEONARDO: 2<span class="o">(</span>SDA<span class="o">)</span>, 3<span class="o">(</span>SCL<span class="o">)</span>, ... +</span></span><span class="line"><span class="cl"><span class="c1">#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_ADDRESS 0x3C ///&lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32</span> +</span></span><span class="line"><span class="cl">Adafruit_SSD1306 display<span class="o">(</span>SCREEN_WIDTH, SCREEN_HEIGHT, <span class="p">&amp;</span>Wire, OLED_RESET<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define NUMFLAKES 10 // Number of snowflakes in the animation example</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_HEIGHT 16</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_WIDTH 16</span> +</span></span><span class="line"><span class="cl">static const unsigned char PROGMEM logo_bmp<span class="o">[]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="o">{</span> 0b00000000, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11110011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11111110, 0b11111000, +</span></span><span class="line"><span class="cl"> 0b01111110, 0b11111111, +</span></span><span class="line"><span class="cl"> 0b00110011, 0b10011111, +</span></span><span class="line"><span class="cl"> 0b00011111, 0b11111100, +</span></span><span class="line"><span class="cl"> 0b00001101, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00011011, 0b10100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01111100, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01110000, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00000000, 0b00110000 <span class="o">}</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void setup<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.begin<span class="o">(</span>115200<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // <span class="nv">SSD1306_SWITCHCAPVCC</span> <span class="o">=</span> generate display voltage from 3.3V internally +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span>!display.begin<span class="o">(</span>SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS<span class="o">))</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;SSD1306 allocation failed&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span><span class="p">;</span> // Don<span class="s1">&#39;t proceed, loop forever +</span></span></span><span class="line"><span class="cl"><span class="s1"> } +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show initial display buffer contents on the screen -- +</span></span></span><span class="line"><span class="cl"><span class="s1"> // the library initializes this with an Adafruit splash screen. +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); // Pause for 2 seconds +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Clear the buffer +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.clearDisplay(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Draw a single pixel in white +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.drawPixel(10, 10, SSD1306_WHITE); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show the display buffer on the screen. You MUST call display() after +</span></span></span><span class="line"><span class="cl"><span class="s1"> // drawing commands to make them visible on screen! +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); +</span></span></span><span class="line"><span class="cl"><span class="s1"> // display.display() is NOT necessary after every single drawing command, +</span></span></span><span class="line"><span class="cl"><span class="s1"> // unless that&#39;</span>s what you want...rather, you can batch up a bunch of +</span></span><span class="line"><span class="cl"> // drawing operations and <span class="k">then</span> update the screen all at once by calling +</span></span><span class="line"><span class="cl"> // display.display<span class="o">()</span>. These examples demonstrate both approaches... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawtriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfilltriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawchar<span class="o">()</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawstyles<span class="o">()</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testscrolltext<span class="o">()</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawbitmap<span class="o">()</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Invert and restore display, pausing in-between +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">false</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testanimate<span class="o">(</span>logo_bmp, LOGO_WIDTH, LOGO_HEIGHT<span class="o">)</span><span class="p">;</span> // Animate bitmaps +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void loop<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int16_t i<span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn line +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.width<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> <span class="m">2</span> seconds +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so rectangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-i*2, display.height<span class="o">()</span>-i*2, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawCircle<span class="o">(</span>display.width<span class="o">()</span>/2, display.height<span class="o">()</span>/2, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so circles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillCircle<span class="o">(</span>display.width<span class="o">()</span> / 2, display.height<span class="o">()</span> / 2, i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn circle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so round-rects alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so triangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0, 0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.cp437<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> // Use full <span class="m">256</span> char <span class="s1">&#39;Code Page 437&#39;</span> font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Not all the characters will fit on the display. This is normal. +</span></span><span class="line"><span class="cl"> // Library will draw what it can and the rest will be clipped. +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;256<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span><span class="nv">i</span> <span class="o">==</span> <span class="s1">&#39;\n&#39;</span><span class="o">)</span> display.write<span class="o">(</span><span class="s1">&#39; &#39;</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> display.write<span class="o">(</span>i<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0,0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_BLACK, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;inverse&#39;</span> text +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>3.141592<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;0x&#34;</span><span class="o">))</span><span class="p">;</span> display.println<span class="o">(</span>0xDEADBEEF, HEX<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>10, 0<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;scroll&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show initial text +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>100<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Scroll in various directions, pausing in-between: +</span></span><span class="line"><span class="cl"> display.startscrollright<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrollleft<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagright<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagleft<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span> +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.width<span class="o">()</span> - LOGO_WIDTH <span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.height<span class="o">()</span> - LOGO_HEIGHT<span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define XPOS 0 // Indexes into the &#39;icons&#39; array in function below</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define YPOS 1</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define DELTAY 2</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int8_t f, icons<span class="o">[</span>NUMFLAKES<span class="o">][</span>3<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Initialize <span class="s1">&#39;snowflake&#39;</span> positions +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;x: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; y: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; dy: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span> <span class="o">{</span> // Loop forever... +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear the display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Draw each snowflake: +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, bitmap, w, h, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show the display buffer on the screen +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>200<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> 1/10 second +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Then update coordinates of each flake... +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> +<span class="o">=</span> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> // If snowflake is off the bottom of the screen... +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> &gt;<span class="o">=</span> display.height<span class="o">())</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // Reinitialize to a random position, just off the top +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在此示例中有几点注意事项:</p> +<ul> +<li>在每一份添加的示例工程中,我们都必须要包含头文件 <code>#include &lt;Arduino.h&gt;</code></li> +<li>由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 <code>0x3c</code>,所以对应示例工程中的 <code>SCREEN_ADDRESS</code>需要修改为 <code>0X3C</code></li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061.png" +width="533" +height="143" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190157061" +class="gallery-image" +data-flex-grow="372" +data-flex-basis="894px" +></p> +<ul> +<li>由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍</li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190348607" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:</p> +<table> +<thead> +<tr> +<th style="text-align:center">pin</th> +<th style="text-align:center">func</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">P203</td> +<td style="text-align:center">i2c0-sda</td> +</tr> +<tr> +<td style="text-align:center">P202</td> +<td style="text-align:center">i2c0-scl</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">vcc</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">gnd</td> +</tr> +</tbody> +</table> +<p>接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695.png" +width="813" +height="431" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123191534695" +class="gallery-image" +data-flex-grow="188" +data-flex-basis="452px" +></p> +<p>查看demo:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo.gif" +width="1280" +height="720" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif 1024w" +loading="lazy" +alt="demo" +class="gallery-image" +data-flex-grow="177" +data-flex-basis="426px" +></p>【经验分享】如何让你的终端实现自动补齐、历史回溯https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/cover.jpg" alt="Featured image of post 【经验分享】如何让你的终端实现自动补齐、历史回溯" /><h2 id="linux下配置">Linux下配置 +</h2><p>在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:</p> +<h3 id="步骤-1-安装-zsh">步骤 1: 安装 zsh +</h3><p>确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install zsh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-2-安装-oh-my-zsh">步骤 2: 安装 oh-my-zsh +</h3><p>在终端中运行以下命令来安装 oh-my-zsh:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者,如果你没有安装 <code>curl</code>,可以使用 <code>wget</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-3-更改主题">步骤 3: 更改主题 +</h3><ol> +<li> +<p>打开 <code>~/.zshrc</code> 文件以编辑它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nano ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>找到 <code>ZSH_THEME</code> 行并更改主题。你可以在 <a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" target="_blank" rel="noopener" +>oh-my-zsh 主题库</a>中选择一个主题,例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">ZSH_THEME</span><span class="o">=</span><span class="s2">&#34;agnoster&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>保存并关闭文件。</p> +</li> +</ol> +<h3 id="步骤-4-启用历史回溯">步骤 4: 启用历史回溯 +</h3><p>oh-my-zsh 默认启用历史回溯。确保 <code>~/.zshrc</code> 中没有明确禁用该功能的设置。检查是否存在以下行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;yyyy-mm-dd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-5-重新启动-zsh-或打开新终端">步骤 5: 重新启动 zsh 或打开新终端 +</h3><p>在更改 <code>~/.zshrc</code> 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 <code>zsh</code> 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。</p> +<h2 id="windwos下配置">Windwos下配置 +</h2><p>在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 <code>PSReadLine</code> 模块,它提供了丰富的命令行编辑和历史记录功能。</p> +<p>以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:</p> +<ol> +<li> +<p><strong>安装 PSReadLine 模块:</strong> +打开 PowerShell 终端,并执行以下命令来安装 <code>PSReadLine</code> 模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">PSReadLine</span> <span class="n">-Force</span> <span class="n">-SkipPublisherCheck</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>配置 PowerShell 用户配置文件:</strong> +执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">notepad</span> <span class="nv">$PROFILE</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>在配置文件中添加以下行:</strong> +在打开的配置文件中,添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Import-Module</span> <span class="n">PSReadLine</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-HistoryNoDuplicates:</span><span class="vm">$false</span> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-EditMode</span> <span class="n">Emacs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存并关闭文件。</p> +</li> +<li> +<p><strong>重新启动 PowerShell:</strong> +关闭当前的 PowerShell 终端,并重新打开一个新的终端。</p> +</li> +<li> +<p><strong>使用历史记录搜索:</strong> +可以在 PowerShell 终端中使用 <code>Ctrl + r</code> 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。</p> +</li> +</ol>【嵌入式素养提升】MPU与MCUhttps://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/<img src="https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover.jpg" alt="Featured image of post 【嵌入式素养提升】MPU与MCU" /><h2 id="mpu与mcu">MPU与MCU +</h2><p>MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。</p> +<p>但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。</p> +<p>在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。</p> +<p>由于主要完成“控制”相关的任务,所以称为 <code>Controller</code>。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。</p> +<p>而<code>Processor</code>,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。</p> +<p>以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。</p> +<p>为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。</p> +<p>从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。</p> +<p>总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。</p>【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul>【经验分享】WSL中使用USB设备https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【经验分享】WSL中使用USB设备" /><h2 id="具体步骤">具体步骤: +</h2><p>首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:</p> +<blockquote> +<p>下载链接:https://github.com/dorssel/usbipd-win/releases</p> +</blockquote> +<p>同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开wsl ubuntu终端使用命令:<code>uname -r</code>得到版本号,同时根据版本号使用管理员模式新建目录</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7.png" +width="587" +height="103" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="569" +data-flex-basis="1367px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases</p> +<p>这里的版本就是你使用命令 <code>uname -r</code> 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下</p> +<p>然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl">$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ <span class="o">&amp;&amp;</span> sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后将内核的一些配置信息复制到当前文件夹下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp /proc/config.gz config.gz +</span></span><span class="line"><span class="cl">$ sudo gunzip config.gz +</span></span><span class="line"><span class="cl">$ sudo mv config .config +</span></span></code></pre></td></tr></table> +</div> +</div><p>接着我们执行menuconfig命令打开图形化菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入如下路径:<code>&gt; Device Drivers &gt; USB support</code></p> +<p>下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Device Drivers -&gt; USB Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB announce new devices +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB Modem <span class="o">(</span>CDC ACM<span class="o">)</span> support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; VHCI HCD +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support -&gt; USB FTDI Single port Serial Driver +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时记得关闭 <code>Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; Debug messages for USB/IP</code>这一选项,否则调试信息会非常影响你的使用体验</p> +<p>另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>内核编译期间发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" +width="1069" +height="344" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="310" +data-flex-basis="745px" +></p> +<p>这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install dwarves +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo make -j8 <span class="o">&amp;&amp;</span> sudo make modules_install -j8 <span class="o">&amp;&amp;</span> sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现又产生了报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac.png" +width="932" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="300" +data-flex-basis="721px" +></p> +<p>查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo vi .config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装内核时发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png.webp" +width="1200" +height="176" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="681" +data-flex-basis="1636px" +></p> +<p>解决方式有两种:</p> +<ul> +<li>1.可以选择在<code>.config</code>中禁用宏<code>CONFIG_X86_X32</code></li> +<li>2.找到合适的binutils版本使其能够编译</li> +</ul> +<p>我选择的是第一种,根据我在网上找到的说法是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>所以我选择禁用宏<code>CONFIG_X86_X32</code>,之后继续执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make modules_install -j8 +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>之后就可以选择编译 USBIP 工具了:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> tools/usb/usbip +</span></span><span class="line"><span class="cl">$ sudo ./autogen.sh +</span></span><span class="line"><span class="cl">$ sudo ./configure +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>复制工具库位置,以便 usbip 工具可以获取到:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装 usb.ids 以便显示 USB 设备的名称:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt-get install hwdata +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启WSL:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ wsl --shutdown +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面进行测试是否成功: +打开powershell:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl list +</span></span></code></pre></td></tr></table> +</div> +</div><p>假设我们需要在wsl使用的 usb 设备为 <code>ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3)</code>,设备id为 <code>0483:374b</code></p> +<p>我们使用命令附加设备到 wsl2 中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;0483:374b&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" +width="1200" +height="408" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="294" +data-flex-basis="705px" +></p> +<p>此时我们打开一个 wsl 终端,使用命令 <code>lsusb</code> 即可看到附加到 wsl 的设备</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96.png" +width="1146" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="369" +data-flex-basis="887px" +></p> +<p>然后我们再次回到 powershell ,执行 <code>usbipd wsl list</code>命令,可以看到此时的 usb 设备已经成功添加到 wsl 了</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" +width="1200" +height="572" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="209" +data-flex-basis="503px" +></p>【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Linux系统开发】Linux常见开发汇总https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover.jpg" alt="Featured image of post 【Linux系统开发】Linux常见开发汇总" /><h2 id="1vmware-tools-灰色无法点击">1.vmware tools 灰色无法点击 +</h2><p>执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get update +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get upgrade +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install open-vm-tools-desktop -y +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2linux安装搜狗输入法">2.linux安装搜狗输入法 +</h2><p>终端安装 fcitx</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install fcitx +</span></span></code></pre></td></tr></table> +</div> +</div><p>到搜狗官方下载 deb 包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://shurufa.sogou.com/linux" target="_blank" rel="noopener" +>https://shurufa.sogou.com/linux</a></li> +</ul> +</blockquote> +<p>使用linux自带的安装程序安装输入法后,安装如下输入法依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 +</span></span><span class="line"><span class="cl">sudo apt install libgsettings-qt1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启即可</p> +<h2 id="3cmake安装指定版本">3.Cmake安装指定版本 +</h2><p>首先去官网下载所需版本的压缩包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://cmake.org/files/" target="_blank" rel="noopener" +>https://cmake.org/files/</a></li> +</ul> +</blockquote> +<p>执行解压命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -zxv -f cmake-3.22.6.tar.gz +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装相关依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install g++ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install make +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入解压后的cmake文件,执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./bootstrap +</span></span></code></pre></td></tr></table> +</div> +</div><p>编译构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">make +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo make install +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4ubuntu中使用-st-link">4.ubuntu中使用 st-link +</h2><p>安装依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc +</span></span></code></pre></td></tr></table> +</div> +</div><p>依次执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># download source code</span> +</span></span><span class="line"><span class="cl">git clone https://github.com/stlink-org/stlink +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> stlink +</span></span><span class="line"><span class="cl"><span class="c1"># build</span> +</span></span><span class="line"><span class="cl">cmake . +</span></span><span class="line"><span class="cl">make +</span></span><span class="line"><span class="cl"><span class="c1"># install</span> +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bin +</span></span><span class="line"><span class="cl">sudo cp st-* /usr/local/bin +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ../lib +</span></span><span class="line"><span class="cl">sudo cp *.so* /lib32 +</span></span><span class="line"><span class="cl"><span class="c1"># add rules</span> +</span></span><span class="line"><span class="cl">sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ +</span></span><span class="line"><span class="cl">sudo udevadm control --reload-rules +</span></span><span class="line"><span class="cl">sudo udevadm trigger +</span></span></code></pre></td></tr></table> +</div> +</div><p>尝试烧录代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#check if st-link is plugged</span> +</span></span><span class="line"><span class="cl">sudo st-info --probe +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># write hex</span> +</span></span><span class="line"><span class="cl">sudo st-flash --format ihex write myapp.hex +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 一般下载一次,会失败,需要刷入两次;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># write bin</span> +</span></span><span class="line"><span class="cl">sudo st-flash write in.bin 0x8000000 <span class="c1">#stm32f4xx</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># read bin</span> +</span></span><span class="line"><span class="cl">st-flash <span class="nb">read</span> out.bin 0x8000000 0x1000 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># restart</span> +</span></span><span class="line"><span class="cl"><span class="c1"># 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作</span> +</span></span><span class="line"><span class="cl">sudo st-flash reset +</span></span></code></pre></td></tr></table> +</div> +</div><p>具体的GDB调试可以参考这篇文章:</p> +<blockquote> +<ul> +<li><a class="link" href="https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html" target="_blank" rel="noopener" +>https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html</a></li> +</ul> +</blockquote>【Git版本控制】Github和Gitlab同时使用sshhttps://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover.jpg" alt="Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh" /><h2 id="前言">前言 +</h2><p>最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下</p> +<h2 id="本地生成公私密钥">本地生成公私密钥 +</h2><p>首先确保把之前的 ssh 信息清除,也可以将整个 <code>~/.ssh</code> 目录删除</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rm -rf ~/.ssh/* +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们分别生成 Github 和 Gitlab账号的 SSH 密钥</p> +<ul> +<li>Github 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意不要选择其他操作,一路回车即可</p> +<p>此时打开 <code>~/.ssh/</code> 目录可以看到生成了四个文件:<code>github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub</code></p> +<p>其中 <code>.pub</code> 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存</p> +<h2 id="远程仓库-ssh-填写公钥密钥">远程仓库 SSH 填写公钥密钥 +</h2><p>我们先打开 Github 的 Settings选项,然后选择 <code>SSH and GPG keys-&gt;New SSH key</code> ,<code>Title</code>可以随意拟定,<code>Key</code>需要查看刚刚的 <code>github_id-rsa.pub</code> 文件,并且复制到 Gitlab 的<code>key</code>一栏中;</p> +<p>Gitlab 的操作方式与 Github 类似,具体步骤:</p> +<p>打开 <code>Gitlab -&gt; 用户设置 -&gt; SSH密钥</code> ,在密钥一栏填入 <code>gitlab_id-rsa.pub</code>文件中的具体值,标题自拟即可。</p> +<h2 id="配置不同-host-的-ssh-key">配置不同 Host 的 SSH Key +</h2><p>回到 <code>~/.ssh/</code> 目录下,并且创建一个名为 <code>config</code> 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#github</span> +</span></span><span class="line"><span class="cl">Host github.com +</span></span><span class="line"><span class="cl"> Hostname ssh.github.com +</span></span><span class="line"><span class="cl"> Port <span class="m">443</span> +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/github_id-rsa +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#gitlab</span> +</span></span><span class="line"><span class="cl">host git.rt-thread.com +</span></span><span class="line"><span class="cl"> Hostname git.rt-thread.com +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/figure/ssh-config.png" +loading="lazy" +></p> +<h2 id="验证">验证 +</h2><p>使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置</p> +<ul> +<li>Github SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@github.com +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@rt-thread.com +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功</p> +<p><img src="https://kurisaw.github.io/figure/valid-ssh.png" +loading="lazy" +></p>【Matter】CHIP设备层设计笔记https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/<img src="https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover.jpg" alt="Featured image of post 【Matter】CHIP设备层设计笔记" /><h1 id="chip设备层设计笔记">CHIP设备层设计笔记 +</h1><p>本文档包含与 CHIP 设备层 ( <code>src/platform</code>) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。</p> +<p>这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。</p> +<p>本文档包含以下部分:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Device-Layer-Adaptation-Patterns" target="_blank" rel="noopener" +>设备层适配模式</a></li> +</ul> +<hr> +<h3 id="设备层适配模式">设备层适配模式 +</h3><p>设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。</p> +<p>CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。</p> +<p>作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。</p> +<p>为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。</p> +<p>尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。</p> +<p>以下各节描述了用于实现这些目标的一些模式。</p> +<ol> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Interface-and-Implementation-Classes" target="_blank" rel="noopener" +>接口和实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Method-Forwarding" target="_blank" rel="noopener" +>方法转发</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Target-Platform-Selection" target="_blank" rel="noopener" +>目标平台选择</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Generic-Implementation-Classes" target="_blank" rel="noopener" +>通用实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Overriding-Generic-Behaviors" target="_blank" rel="noopener" +>覆盖通用行为</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Multiple-Inheritance-and-Subclassing-of-Generic-Implementations" target="_blank" rel="noopener" +>通用实现的多重继承和子类化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Static-Virtualization-of-Generic-Implementation-Behavior" target="_blank" rel="noopener" +>通用实现行为的静态虚拟化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#-ipp-files-and-explicit-template-instantiation" target="_blank" rel="noopener" +>.cpp 文件和显式模板实例化</a></li> +</ol> +<hr> +<h3 id="接口和实现类">接口和实现类 +</h3><p>CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。</p> +<p>外部可见的<em><strong>抽象接口类</strong></em>定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。</p> +<p>实现<em><strong>类</strong></em>提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。</p> +<p>设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。</p> +<p>抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀<code>Impl</code>。在所有情况下,实现类都需要从其接口类公开继承。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for a specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="方法转发">方法转发 +</h3><p>接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。<code>this</code>这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪的重复模板模式</a> ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,<code>ImplClass</code>使转发方法定义更加简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* forward method call... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>作为转发方法目标的实现类上的方法称为*<strong>实现方法*</strong>。每一种转发方法都必须有相应的实现方法。</p> +<p>前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。</p> +<p>实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Let the forwarding methods on ConfigurationManager call implementation +</span></span><span class="line"><span class="cl"> methods on this class. */ +</span></span><span class="line"><span class="cl"> friend ConfigurationManager; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">private: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR _Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding implementation method... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding static implementation method... */ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="目标平台选择">目标平台选择 +</h3><p>实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of ConfigurationManager.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#define CONFIGURATIONMANAGERIMPL_HEADER \ +</span></span><span class="line"><span class="cl"> &lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h&gt; +</span></span><span class="line"><span class="cl">#include CONFIGURATIONMANAGERIMPL_HEADER +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span></code></pre></td></tr></table> +</div> +</div><p>该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。</p> +<p>每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如<code>ESP32</code>)。所有此类文件都具有相同的文件名(例如<code>ConfigurationManagerImpl.h</code>),并且每个文件都包含类似名称的类的定义(<code>ConfigurationManagerImpl</code>)。</p> +<p>特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 <code>src/adaptations/device-layer/ESP32</code>)。与特定于平台的头目录一样,这些子目录以目标平台命名。</p> +<p>设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 <code>--device-layer=&lt;target-platform&gt;</code>。传递 &ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET ESP32 +</span></span><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET_ESP32 1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>&ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。</p> +<h3 id="通用实现类">通用实现类 +</h3><p>通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。</p> +<p>为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。</p> +<p>通用实现基类被实现为遵循 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪重复模板模式的</a>C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Implementation provided by +</span></span><span class="line"><span class="cl"> generic base class. */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); /* &lt;-- Invoked when GetDeviceId() called. */ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="覆盖通用行为">覆盖通用行为 +</h3><p>如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。</p> +<p>新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using GenericImpl = GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Call the generic implementation to get the device id. */ +</span></span><span class="line"><span class="cl"> uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Special case the situation where the device id is not known. */ +</span></span><span class="line"><span class="cl"> if (deviceId == kNodeIdNotSpecified) { +</span></span><span class="line"><span class="cl"> deviceId = PLATFORM_DEFAULT_DEVICE_ID; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return deviceId; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现的多重继承和子类化">通用实现的多重继承和子类化 +</h3><p>具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericWiFiConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;, /* &lt;-- WiFi features */ +</span></span><span class="line"><span class="cl"> public GenericThreadConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Thread features */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on all platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on FreeRTOS platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl_FreeRTOS +</span></span><span class="line"><span class="cl"> : public GenericPlatformManagerImpl&lt;ImplClass&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现行为的静态虚拟化">通用实现行为的静态虚拟化 +</h3><p>在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。</p> +<p>例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过<code>GetDeviceId()</code>从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。</p> +<p><code>this</code>遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数<code>Impl()</code>有助于使代码简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericConfigurationManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ConfigurationManagerImpl</span> <span class="n">final</span> +</span></span><span class="line"><span class="cl"> <span class="p">:</span> <span class="n">public</span> <span class="n">ConfigurationManager</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">public</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">friend</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">delegate</span> <span class="n">to</span> <span class="n">the</span> <span class="n">implementation</span> <span class="k">class</span> <span class="n">to</span> <span class="n">read</span> <span class="n">the</span> <span class="s1">&#39;device-id&#39;</span> <span class="n">config</span> <span class="n">value</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="err">“</span><span class="n">device</span><span class="o">-</span><span class="n">id</span><span class="err">”</span><span class="p">,</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">ConfigurationManagerImpl</span><span class="p">::</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">read</span> <span class="n">value</span> <span class="n">from</span> <span class="n">platform</span><span class="o">-</span><span class="n">specific</span> <span class="n">key</span><span class="o">-</span><span class="n">value</span> <span class="n">store</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。</p> +<p>同样,委托是通过转换<code>this</code>指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericPlatformManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">Delegate</span> <span class="n">work</span> <span class="n">to</span> <span class="n">method</span> <span class="n">that</span> <span class="n">can</span> <span class="n">be</span> <span class="n">overridden</span> <span class="n">by</span> <span class="n">implementation</span> <span class="k">class</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">provide</span> <span class="n">default</span> <span class="n">implementation</span> <span class="n">of</span> <span class="n">DispatchEventToApplication</span><span class="p">()</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="cpp-文件和显式模板实例化">.cpp 文件和显式模板实例化 +</h3><p>C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。</p> +<p>为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀<code>.cpp</code>。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.cpp */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">CHIP_ERROR GenericConfigurationManagerImpl&lt;ImplClass&gt;::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。<a class="link" href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation" target="_blank" rel="noopener" +>为了避免这种情况,设备层使用显式模板实例化</a>的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件<code>extern template class</code>在使用模板类之前都包含一个声明。这告诉编译器<em>不要</em>在该上下文中实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.h */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Instruct the compiler to instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span></span><span class="line"><span class="cl"><span class="c1">// class only when explicitly asked to do so. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">extern</span> <span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并<code>template class</code>使用定义来强制显式实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.cpp */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Fully instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; class. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。</p>【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)" /><h1 id="如何在linux平台下测试matter应用级通信虚拟设备">如何在Linux平台下测试Matter应用级通信(虚拟设备) +</h1><hr> +<h2 id="准备工作">准备工作 +</h2><h3 id="1-递归克隆matter仓库">1. 递归克隆Matter仓库 +</h3><p>执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果克隆过程中发生报错,请执行如下命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout v1.0 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2-matter依赖项安装">2. Matter依赖项安装 +</h3><p>Matter 构建依赖于以下软件包及环境库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果通过<code> build_examples.py</code> 和 <code>-with-ui</code> 变体进行构建,也要安装 SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-matter环境构建">3. Matter环境构建 +</h3><p>执行<code>scripts/activate.sh</code>脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190833624.png" +loading="lazy" +alt="image-20230619083303148" +></p> +<p>如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-安装zap">4. 安装zap +</h3><blockquote> +<p>注意:zap 包目前不可用<code>arm64</code>(比如在 Raspberry PI 上编译时)。</p> +</blockquote> +<ul> +<li>**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node -v +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果安装的话不出意外会出现版本号。</p> +<ul> +<li><strong>Step2:zap安装</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> connectedhomeip/scripts/tools/zap +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">python3 zap_download.py +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是安装日志:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip +</span></span><span class="line"><span class="cl">2023-06-19 13:29:20 root INFO Data downloaded, extracting ... +</span></span><span class="line"><span class="cl">2023-06-19 13:29:25 root INFO Done extracting. +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_INSTALL_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step3:配置zap环境变量</strong></li> +</ul> +<p>我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为<code>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly</code>,在此目录下有个 zap 脚本,我们这个位置一定要记住!!</p> +<p>设置<code>ZAP_DEVELOPMENT_PATH</code>环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step4:运行zap引导程序</strong></li> +</ul> +<p>执行如下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./run_zaptool.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>效果如下:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191346155.png" +loading="lazy" +alt="image-20230619134658521" +></p> +<ul> +<li><strong>Step4:为了方便我们后续使用zap,我们设置root终端下自启动:</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">vi ~/.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>.bashrc</code>文件最末添加如下代码,也就是配置zap环境变量</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出!</p> +<h2 id="应用程序构建">应用程序构建 +</h2><p>在官方文档中提供有两种构建方式:</p> +<ul> +<li>通过脚本构建</li> +<li>使用 Gn 和 Ninja 命令构建</li> +</ul> +<h3 id="1-通过脚本构建">1. 通过脚本构建 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build_script.sh EXAMPLE_DIR OUTPUT_DIR <span class="o">[</span>ARGUMENTS<span class="o">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>build_script.sh</code> 是脚本的文件名;</li> +<li><code>EXAMPLE_DIR</code> 是示例项目的目录路径;</li> +<li><code>OUTPUT_DIR</code> 是构建输出的目录路径;</li> +<li><code>[ARGUMENTS]</code> 是可选的其他参数,用于设置gn和ninja命令的选项。</li> +</ul> +<h4 id="11-构建示例">1.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ <span class="nv">chip_tests_zap_config</span><span class="o">=</span><span class="se">\&#34;</span>app1<span class="se">\&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190835972.png" +loading="lazy" +alt="image-20230619083551820" +></p> +<h4 id="12-运行构建">1.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./out/simulated/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190843752.png" +loading="lazy" +alt="image-20230619084309631" +></p> +<h3 id="2-通过-gn-和-ninja-构建应用程序">2. 通过 gn 和 ninja 构建应用程序 +</h3><h4 id="21-构建示例">2.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span><span class="line"><span class="cl">gn gen --check --root<span class="o">=</span>examples/placeholder/linux out/simulated --args<span class="o">=</span><span class="s2">&#34;chip_tests_zap_config=\&#34;app1\&#34;&#34;</span> +</span></span><span class="line"><span class="cl">ninja -C out/simulated +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22-运行构建">2.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./out/app1/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191510937.png" +loading="lazy" +alt="image-20230619151054483" +></p> +<h2 id="测试应用程序">测试应用程序 +</h2><p>在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191513515.png" +loading="lazy" +alt="image-20230619151353417" +></p> +<p>我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> out/debug +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./chip-tool onoff on 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff off 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> accepted-command-list 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> on-time 0x654321 <span class="m">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191530858.png" +loading="lazy" +alt="image-20230619153015727" +></p> +<p>具体更多的使用命令可参考:<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md" target="_blank" rel="noopener" +>Chip tool</a></p> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/simulated_device_linux.md" target="_blank" rel="noopener" +>simulated_device_linux</a></li> +<li><a class="link" href="https://github.com/project-chip/zap" target="_blank" rel="noopener" +>zap</a></li> +</ul>【Matter】Matter学习笔记1https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/<img src="https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover.jpg" alt="Featured image of post 【Matter】Matter学习笔记1" /><h1 id="matter学习笔记1">Matter学习笔记1 +</h1><hr> +<p>在了解Matter之前,可以选择先了解以下前提知识:</p> +<ul> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118389957" target="_blank" rel="noopener" +>matter网络基础之—Thread</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118553988" target="_blank" rel="noopener" +>matter网络基础之—Wi-Fi</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/119253287" target="_blank" rel="noopener" +>边界路由器,网关和Wi-Fi接入点</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/120067170" target="_blank" rel="noopener" +>Thread地址(IPv6 and RLOC16)</a></li> +</ul> +<blockquote> +<p>以上资料来自CSDN博主:<a class="link" href="https://blog.csdn.net/qq_42860989" target="_blank" rel="noopener" +>Eagle115</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。</p> +<p>Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个<strong>统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准</strong>。</p> +<p>Matter 作为一个<strong>应用级的协议</strong>,向下屏蔽了<strong>设备制造商的生态和系统,让各种智能家居设备之间能相互通信</strong>。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。</p> +<p>Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:</p> +<ul> +<li><strong>低功耗蓝牙技术</strong>:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。</li> +<li><strong>二维码进行配置</strong>:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。</li> +<li><strong>Wi-Fi 技术进行高速数据传输</strong>:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。</li> +<li><strong>Thread 协议进行低速数据传输</strong>:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。</li> +</ul> +<h2 id="matter协议架构">Matter协议架构 +</h2><h3 id="1matter-over-ipv6">1.Matter Over IPV6 +</h3><p>该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。</p> +<p>IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。</p> +<p>下面是IPV4 和 IPV6 的一些区别:</p> +<table> +<thead> +<tr> +<th style="text-align:center">区别</th> +<th style="text-align:center">IPV4</th> +<th style="text-align:center">IPV6</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">地址长度</td> +<td style="text-align:center">32 bits</td> +<td style="text-align:center">128 bits</td> +</tr> +<tr> +<td style="text-align:center">地址数量</td> +<td style="text-align:center">约<strong>4x10^9</strong></td> +<td style="text-align:center">约<strong>3.4×10^38</strong></td> +</tr> +<tr> +<td style="text-align:center">地址类型</td> +<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> +<td style="text-align:center">通过 DHCPv6 动态分配</td> +</tr> +<tr> +<td style="text-align:center">安全性</td> +<td style="text-align:center">IPsec(Internet协议安全标准) 为可选项</td> +<td style="text-align:center">IPsec 为默认选项</td> +</tr> +<tr> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +</tr> +</tbody> +</table> +<h3 id="2matter协议架构">2.Matter协议架构 +</h3><p>Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121952614.png" +loading="lazy" +></p> +<p>为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此<strong>天生具备IP连接能力</strong>,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;</p> +<p>Matter 还支持<strong>桥接</strong>等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行<strong>Bridge</strong>;</p> +<p>由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!</p> +<h3 id="3matter标准协议架构">3.Matter标准协议架构 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121138795.png" +loading="lazy" +></p> +<p><strong>Matter标准协议架构总体流程分析:</strong></p> +<p>首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议<a class="link" href="" >Message Reliability Protocol</a>);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。</p> +<p>后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!</p> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p>原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。</p> +<p>在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。</p> +<p>Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为<strong>Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层</strong>。而 <strong>6LoWPAN协议</strong> 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。</p> +<p>因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。</p> +<h3 id="mesh组网">Mesh组网 +</h3><p>在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。</p> +<p>目前最流行的全屋WiFi方案主要有两种:<strong>Mesh路由器组网</strong>和<strong>AC+AP</strong>两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。</p> +<p>无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,<strong>无线Mesh网络</strong>中的<strong>AP</strong>可以采用<strong>无线连接</strong>的方式进行互连,并且<strong>AP间可以建立多跳的无线链路</strong>。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +loading="lazy" +alt="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +></p> +<p>这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:</p> +<h3 id="1单一网络拓扑">1.单一网络拓扑 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121601076.png" +loading="lazy" +></p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121516744.png" +loading="lazy" +></p> +<p>在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是<strong>Thread/802.15.4网络</strong>、<strong>Wi-Fi网络</strong>或<strong>以太网网络</strong>。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,<strong>前提是所有段都在链路层桥接</strong>。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。</p> +<p>在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。</p> +<p>在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为<strong>Fabric</strong>。</p> +<blockquote> +<p>注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。</p> +</blockquote> +<h3 id="2星形网络拓扑">2.星形网络拓扑 +</h3><ul> +<li><strong>AP(Access Point)</strong>:WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。</li> +<li><strong>STA(Station)</strong>:STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。</li> +<li><strong>BR(Border Router)</strong>:指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。</li> +<li><strong>ED(End device)</strong>:指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +<li><strong>R(Router)</strong>:指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。</li> +<li><strong>SED(Sleepy End Device)</strong>:指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121605090.png" +loading="lazy" +></p> +<p>星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。<strong>外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。</strong></p> +<p>在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。</p> +<p>该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。</p> +<blockquote> +<p>注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。</p> +</blockquote> +<h2 id="设备数据模型date-model">设备数据模型(Date Model) +</h2><p>在 Matter 中的设备具有明确定义的<strong>数据模型</strong> (<strong>DM</strong>),这是对设备功能的分层建模。在此层次结构的顶层,有一个<strong>Device</strong>。</p> +<h3 id="1设备和端点nodeendpoint">1.设备和端点(Node、Endpoint) +</h3><p>所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。</p> +<p>一组节点包含了多组<strong>Endpoint(端点)</strong>。<strong>而每个端点都封装了一个功能集</strong>。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122042737.png" +loading="lazy" +></p> +<h3 id="2节点角色node-roles">2.节点角色(Node roles) +</h3><p>在Matter 中,每一个物理设备都被称之为<strong>Node</strong>,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!</p> +<p><strong>Node roles</strong>是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:</p> +<ul> +<li><strong>Commissioner :执行</strong><a class="link" href="https://developers.home.google.com/matter/primer/commissioning" target="_blank" rel="noopener" +>调试</a>的节点 。</li> +<li><strong>控制器</strong>:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>开/关灯开关</a>)具有控制器角色。</li> +<li><strong>Controlee</strong> : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>On/Off Light Switch</a>。开/关灯开关只能<em>是</em>控制器。它不能是受控人。</li> +<li><strong>OTA Provider</strong> : 可以提供 OTA 软件更新的节点。</li> +<li><strong>OTA 请求者</strong>:可以请求 OTA 软件更新的节点。</li> +</ul> +<h3 id="3集群cluster">3.集群(Cluster) +</h3><p>在一个<strong>Endpoint</strong>中,一个 Node 有一个或多个<strong>Clusters</strong>。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的<em>开/关</em>集群,或可调光端点上的<em>电平控制集群。</em></p> +<p>一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。</p> +<h4 id="31-属性attributes">3.1 属性(Attributes) +</h4><p>在最后一层,我们会找到<strong>Attributes</strong>,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122111729.png" +loading="lazy" +></p> +<h4 id="32-命令commands">3.2 命令(Commands) +</h4><p>除了 Attributes 之外,Clusters 还有<strong>Commands</strong>,也就是<strong>触发 Cluster 进行某种行为的指令</strong>。它们等同于Matter远程过程调用的 DM。命令类似于<em>动词</em>,例如<em>Door Lock</em>集群上的 <em>lock door</em>。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。</p> +<h4 id="33-事件events">3.3 事件(Events) +</h4><p>最后,Clusters 也可能有<strong>Events</strong>,它<strong>可以被认为是过去状态转换的记录</strong>。虽然属性代表<strong>当前状态</strong>,但事件是<strong>过去</strong>的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122122628.png" +loading="lazy" +></p> +<p><code>Endpoint 0</code>作为<code>Utility Clusters</code><strong>保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新</strong>。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。</p> +<h3 id="4-cluster分类">4. Cluster分类 +</h3><p>cluster可以定义为<strong>工具(Utility) Cluster</strong>或<strong>应用(Application) Cluster</strong>。</p> +<h4 id="41-工具utility-cluster">4.1 工具(Utility) Cluster +</h4><p>工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。</p> +<blockquote> +<p>作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。</p> +</blockquote> +<h4 id="42-应用application-cluster">4.2 应用(Application) Cluster +</h4><p>应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。</p> +<blockquote> +<p>应用cluster示例:</p> +<ul> +<li>On/Off cluster —— client向server发送命令</li> +<li>Temperature Measurement cluster —— server向client报告数据</li> +</ul> +</blockquote> +<p>应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。</p> +<blockquote> +<p>示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。</p> +</blockquote> +<h3 id="5-clients-and-servers">5. Clients and Servers +</h3><p>Clusters 可能是<strong>Client Cluster</strong>或<strong>Server Cluster</strong>。服务器是<strong>有状态的</strong>,保存属性、事件和命令;而客户端是 <strong>无状态的</strong>,其职责是启动与远程服务器集群的<strong>交互</strong>,从而执行:</p> +<ul> +<li><strong>读取</strong>和<strong>写入</strong>其远程属性。</li> +<li><strong>读取</strong>其远程事件。</li> +<li><strong>调用</strong>其远程命令。</li> +</ul> +<p>虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有<code>controller/peripheral</code> 或 <code>leader/follower</code>关系。相反,关系是水平的:任何 Cluster 都可以是<strong>Server</strong>或<strong>Client</strong>。因此,<strong>对于不同的集群和功能,节点可能既是服务器又是客户端。</strong></p> +<p>例如,我们可能有两个台灯:<strong>节点 A</strong>和<strong>节点 B</strong>。两个节点都实现了一个<em>开/关灯</em>设备类型。此设备类型包括控制其各自物理光输出的<em>开/关服务器集群。</em></p> +<p>但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现<em>开/关客户端</em>集群,以便它可以控制服务器集群。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122240843.png" +loading="lazy" +></p> +<p>在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。</p> +<p>在下一节中,我们将详细介绍客户端和服务器集群如何交互: <strong>Interaction Model(交互模型)</strong>。</p> +<h2 id="交互模型">交互模型 +</h2><h3 id="1概念">1.概念 +</h3><p>如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。<strong>交互模型</strong>(<strong>IM</strong>),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。</p> +<p><strong>节点通过以下方式相互交互:</strong></p> +<ul> +<li>读取和订阅属性和事件</li> +<li>写入属性</li> +<li>调用命令</li> +</ul> +<p>每当一个节点与另一个节点建立加密通信序列时,它们就构成了<strong>交互</strong>关系。<strong>Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成</strong>,可以理解为 Node 之间的 IM 级消息。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306140839728.png" +loading="lazy" +></p> +<p>Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。</p> +<h4 id="11-发起者initiators-和目标targets">1.1 发起者(Initiators )和目标(Targets) +</h4><p>在Matter中,节点的发起目标被称为<strong>发起者(Initiators )</strong>,而响应的节点则作为<strong>目标(Target)</strong>。一般来说,发起者是客户端集群,而目标是客户端集群。</p> +<h4 id="12-组groups">1.2 组(Groups) +</h4><p>在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。</p> +<p>为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。</p> +<h4 id="13-路径path">1.3 路径(Path) +</h4><p><strong>当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。</strong></p> +<blockquote> +<p>注:Path 也可以使用<strong>Groups</strong>或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。</p> +</blockquote> +<p>Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。</p> +<p>Matter Path 使用规范:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;path&gt; = &lt;node&gt; &lt;endpoint&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span><span class="line"><span class="cl">&lt;path&gt; = &lt;group ID&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。</p> +<h4 id="14-定时和非定时timed--untimed">1.4 定时和非定时(Timed &amp; Untimed) +</h4><p>有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。</p> +<h3 id="2-read-transactions">2. Read Transactions +</h3><p>与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。</p> +<h4 id="21-读取请求操作read-request-action">2.1 读取请求操作(Read Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>在此 Action 中,Initiator 会查询 Target 提供的以下请求:</p> +<ul> +<li><strong>属性请求</strong>:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。</li> +<li><strong>事件请求</strong>:目标请求事件的零个或多个路径列表。</li> +</ul> +<p>目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141108121.png" +loading="lazy" +></p> +<h4 id="22-报告请求数据report-data-action">2.2 报告请求数据(Report Data Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>在此 Action 中,Target 响应:</p> +<ul> +<li><strong>属性报告(Attribute Reports)</strong>:读取操作请求中请求的零个或多个报告属性的列表。</li> +<li><strong>事件报告(Event Reports)</strong>:零个或多个报告事件的列表。</li> +<li><strong>抑制响应(Suppress Response)</strong>:一个标志,用于确定是否应抑制对此操作的<strong>状态响应。</strong></li> +<li><strong>订阅 ID(Subscription ID)</strong>:如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。</li> +</ul> +<h4 id="23-状态响应动作status-response-action">2.3 状态响应动作(Status Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者 -&gt; 目标</strong></p> +</blockquote> +<p>一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。</p> +<p>一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。</p> +<p>状态响应操作仅包含一个<strong>状态字段</strong>,该字段将确认操作成功或显示失败代码。</p> +<h3 id="3-subscription-transaction">3. Subscription Transaction +</h3><h4 id="31-订阅请求操作subscribe-request-action">3.1 订阅请求操作(Subscribe Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。</p> +<p>订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。</p> +<p>订阅请求操作包含:</p> +<ul> +<li><strong>Min Interval Floor(最小间隔层)</strong>:报告之间的最小间隔。</li> +<li><strong>Max Interval Ceiling(最大区间上限)</strong>:报告之间的最大间隔。</li> +<li>Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。</li> +<li>Event Reports(事件报告):零个或多个报告事件的列表。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141332135.png" +loading="lazy" +></p> +<p>在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:<strong>Primed Published Data</strong>。</p> +<p>然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。</p> +<p>目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。</p> +<h4 id="32-订阅响应操作subscribe-response-action">3.2 订阅响应操作(Subscribe Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>这是订阅交易的最后一个操作,并结束了该过程。这包括:</p> +<ul> +<li><strong>Subscription ID(订阅 ID)</strong>:标识订阅的整数。</li> +<li><strong>Min Interval(最小间隔)</strong>:最终确定的报告之间的最小间隔。</li> +<li><strong>Max Interval(最大间隔)</strong>:<em>最终</em>确定<em>的</em>报告之间的最大间隔。</li> +</ul> +<h3 id="4-write-transactions">4. Write Transactions +</h3><h4 id="41-不定时写入事务untimed-write-transaction">4.1 不定时写入事务(Untimed Write Transaction) +</h4><h5 id="411-写请求操作write-request-action">4.1.1 写请求操作(Write Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>与读取请求操作类似,在此操作中,发起者为目标提供:</p> +<ul> +<li><strong>Write Requests(写入请求)</strong>:包含路径和数据的一个或多个元组的列表。</li> +<li><strong>Timed Request(定时请求)</strong>:一个标志,指示此操作是否是定时写入事务的一部分。</li> +<li><strong>Suppress Response(抑制响应)</strong>:指示是否应抑制响应状态操作的标志。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141423081.png" +loading="lazy" +></p> +<h5 id="412-写响应操作write-response-action">4.1.2 写响应操作(Write Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<h5 id="413-不定时写入限制untimed-write-restrictions">4.1.3 不定时写入限制(Untimed Write Restrictions) +</h5><p>写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。</p> +<h4 id="42-定时写入事务timed-write-transaction">4.2 定时写入事务(Timed Write Transaction) +</h4><p>在定时写入事务中比非定时写入事务多了几个步骤。</p> +<h5 id="421-定时请求操作timed-request-action">4.2.1 定时请求操作(Timed request action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。</p> +<h5 id="422-写请求操作write-request-action">4.2.2 写请求操作(Write Request Action) +</h5><p>与前面描述的 <strong>4.1.1 写请求操作</strong> 相同。</p> +<h5 id="423-写响应操作write-response-action">4.2.3 写响应操作(Write Response Action) +</h5><p>与前面描述的 <strong>4.1.2 写响应操作</strong> 相同。</p> +<h5 id="424-定时写入限制timed-write-restrictions">4.2.4 定时写入限制(Timed Write Restrictions) +</h5><p>定时请求动作、写请求动作和写响应动作是单播的。</p> +<h3 id="5调用事务">5.调用事务 +</h3><p><strong>调用事务</strong>用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。</p> +<p>与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 <strong>交互模型:1.4.定时和非定时</strong></p> +<h4 id="51-不定时调用事务">5.1 不定时调用事务 +</h4><h5 id="511-调用请求操作invoke-request-action">5.1.1 调用请求操作(Invoke Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:</p> +<ul> +<li><strong>Invoke Requests(调用请求):集群命令</strong>的路径(PATH)列表 ,以及命令的可选参数,名为 <strong>Command Fields</strong>。</li> +<li>Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。</li> +<li>Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。</li> +<li><strong>Interaction ID</strong>:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。</li> +</ul> +<h5 id="512-调用响应操作invoke-response-action">5.1.2 调用响应操作(Invoke Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:</p> +<ul> +<li><strong>Invoke Responses(调用响应)</strong>:发送的每个调用请求的命令响应或状态列表。</li> +<li>Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。</li> +</ul> +<h5 id="513-不定时调用限制">5.1.3 不定时调用限制 +</h5><p>Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。</p> +<h4 id="52-定时调用事务">5.2 定时调用事务 +</h4><p>与定时写入事务类似,定时调用事务也从定时请求操作开始。</p> +<h5 id="521-定时请求操作">5.2.1 定时请求操作 +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141539988.png" +loading="lazy" +></p> +<h5 id="522-调用请求操作invoke-request-action">5.2.2 调用请求操作(Invoke Request Action) +</h5><p>与前面描述的 <strong>5.1.1 调用请求操作</strong> 相同。</p> +<h5 id="523-调用响应操作invoke-response-action">5.2.3 调用响应操作(Invoke Response Action) +</h5><p>与前面描述的 <strong>5.1.2 调用响应操作</strong> 相同。</p> +<h5 id="524-定时调用限制timed-invoke-restrictions">5.2.4 定时调用限制(Timed Invoke Restrictions) +</h5><p>所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。</p> +<p>Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。</p> +<hr> +<h2 id="参考资料">参考资料 +</h2><ul> +<li><a class="link" href="https://developers.home.google.com/matter/primer/device-data-model#parts_list" target="_blank" rel="noopener" +>https://developers.home.google.com/matter/primer/device-data-model#parts_list</a></li> +<li><a class="link" href="https://www.bilibili.com/video/BV1NL411T7Kj/?spm_id_from=333.788&amp;vd_source=40334d7415493efea293dacb3c13f0b4" target="_blank" rel="noopener" +>Matter技术及关键特性介绍</a></li> +</ul>【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul>【Matter】Matter环境构建参考文档https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/Wed, 24 May 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/<img src="https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/cover.jpg" alt="Featured image of post 【Matter】Matter环境构建参考文档" /><h1 id="matter-环境构建参考文档">Matter 环境构建参考文档 +</h1><hr> +<p>Matter支持用<a class="link" href="https://gn.googlesource.com/gn/" target="_blank" rel="noopener" +>GN</a>配置构建,一个快速且可扩展的元构建系统,生成输入到<a class="link" href="https://ninja-build.org/" target="_blank" rel="noopener" +>ninja</a>。</p> +<h2 id="经过测试的操作系统">经过测试的操作系统 +</h2><p>该构建系统已经在以下操作系统上进行了测试:</p> +<ul> +<li>macOS 10.15</li> +<li>Debian 11 (64 bit required)</li> +<li>Ubuntu 22.04 LTS</li> +</ul> +<h2 id="构建系统的特点">构建系统的特点 +</h2><p>Matter构建系统有以下特点:</p> +<ul> +<li>速度非常快,占用空间小</li> +<li>跨平台处理: Linux, Darwin, Embedded Arm, 等等</li> +<li>多种工具链和跨工具链的依赖性</li> +<li>集成了自动测试框架: ninja check</li> +<li>自省:&ldquo;gn desc&rdquo;。</li> +<li>自动格式化: <code>gn格式</code>。</li> +</ul> +<h2 id="检查matter的代码">检查Matter的代码 +</h2><p>要检查Matter资源库,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="同步子模块">同步子模块 +</h2><p>如果你已经签出了Matter的代码,运行下面的命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="先决条件">先决条件 +</h2><p>在构建之前,你必须安装一些操作系统的特定依赖。</p> +<h3 id="1在linux上安装先决条件">1.在Linux上安装先决条件 +</h3><p>在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\ +</span></span><span class="line"><span class="cl"> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev +</span></span><span class="line"><span class="cl"> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="用户界面的构建">用户界面的构建 +</h4><p>如果通过<code>build_examples.py</code>和<code>with-ui</code>变体构建,也要安装SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在macos上安装先决条件">2.在macOS上安装先决条件 +</h3><p>在macOS上,从 Mac App Store上安装 Xcode 。</p> +<h4 id="用户界面的构建-1">用户界面的构建 +</h4><p>如果构建<code>-with-ui</code>变体,也要安装 SDL2 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">brew install sdl2 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3在raspberry-pi-4上安装先决条件">3.在Raspberry Pi 4上安装先决条件 +</h3><p>完成以下步骤:</p> +<ol> +<li>使用:在 micro SD 卡上<code>rpi-imager</code>安装适用于 arm64 架构的 Ubuntu <em>22.04</em> 64 位<em>服务器操作系统。</em></li> +<li>启动SD卡。</li> +<li>用默认的用户账户 &ldquo;ubuntu &ldquo;和密码 &ldquo;ubuntu &ldquo;登录。</li> +<li>继续执行 <a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>在 Linux 上安装先决条件</a>。</li> +<li>安装一些Raspberry Pi的特定依赖项:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install pi-Bluetooth avahi-utils +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="6"> +<li>安装完 &ldquo;pi-bluetooth &ldquo;后,重新启动你的Raspberry Pi。</li> +</ol> +<h4 id="配置wpa_supplicant以存储永久变化">配置wpa_supplicant以存储永久变化 +</h4><p>默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:</p> +<ol> +<li>编辑 <code>dbus-fi.w1.wpa_supplicant1.service</code> 文件以使用配置文件来代替,运行以下命令:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="2"> +<li>运行以下命令,将wpa_supplicant的启动参数改为提供的值:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="3"> +<li>通过运行以下命令添加<code>wpa-supplicant</code>配置文件:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="4"> +<li>在<code>wpa-supplicant</code>文件中添加以下内容:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl_interface=DIR=/run/wpa_supplicant +</span></span><span class="line"><span class="cl">update_config=1 +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="5"> +<li>重新启动你的Raspberry Pi。</li> +</ol> +<h2 id="安装zap工具">安装ZAP工具 +</h2><p><code>bootstrap.sh</code>将下载一个兼容的ZAP工具版本并将其设置在<code>$PATH</code>。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a> 页面下载。</p> +<h3 id="1linux-arm">1.Linux ARM +</h3><p>Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置<code>$ZAP_DEVELOPMENT_PATH</code>(见下面 <code>使用哪种ZAP</code>一节)。</p> +<p>文件<code>scripts/setup/zap.json</code>包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a>。要作为源代码签出代码,相应的标签应该存在于zap中<a class="link" href="https://github.com/project-chip/zap/tags" target="_blank" rel="noopener" +>repository tags</a> 列表中。</p> +<p>命令示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">RUN <span class="nb">set</span> -x <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> mkdir -p /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git clone https://github.com/project-chip/zap.git /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git checkout <span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm config <span class="nb">set</span> user <span class="m">0</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm ci +</span></span><span class="line"><span class="cl">ENV <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2使用哪种zap">2.使用哪种ZAP +</h3><p>ZAP工具脚本使用以下检测,按重要性排序:</p> +<ul> +<li> +<p><code>$ZAP_DEVELOPMENT_PATH</code>指向一个ZAP检出。</p> +</li> +<li> +<p>如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。</p> +</li> +<li> +<p><code>$ZAP_INSTALL_PATH</code>指向<code>zap-linux.zip</code>或`zap-m</p> +</li> +</ul> +<h2 id="为构建做准备">为构建做准备 +</h2><p>在运行任何其他构建命令之前,<code>scripts/activate.sh</code>的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。</p> +<p>运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1更新环境">1.更新环境 +</h3><p>如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>脚本 <code>scripts/bootstrap.sh</code>从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。</p> +<h2 id="为主机操作系统linux或macos进行构建">为主机操作系统(Linux或macOS)进行构建 +</h2><p>运行以下命令,为主机平台构建所有的源代码、库和测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些命令生成了一个适合调试的配置。要配置一个构建,请指定<code>is_debug=false</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/host --args=&#39;is_debug=false&#39; 。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**目录名称 &ldquo;out/host &ldquo;可以是任何目录,通常是在<code>out</code>目录下构建。这个例子使用 <code>host</code> 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过<code>gn args</code>重新配置。</p> +</blockquote> +<p>要运行所有测试,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host check +</span></span></code></pre></td></tr></table> +</div> +</div><p>要想只运行<code>src/inet/tests</code>中的测试,可以运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host src/inet/tests:test_run +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja: no work to do +</span></span></code></pre></td></tr></table> +</div> +</div><p>这意味着测试在之前的构建中通过了。</p> +</blockquote> +<h2 id="使用build_examplespy">使用<code>build_examples.py</code> +</h2><p>该脚本<code>./scripts/build/build_examples.py</code>提供了一个统一的编译构建接口,可以使用<code>gn</code>、<code>cmake</code>、<code>ninja</code>和其他必要的工具来编译各种平台。</p> +<p>使用 <code>./scripts/build/build_examples.py targets</code> 来查看支持的目标。</p> +<p>构建命令的例子:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 编译并在主机上运行所有测试: +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang) +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个esp32的例子 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个 nrf 示例 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1libfuzzer单元测试">1.<code>libfuzzer</code>单元测试 +</h3><p><code>libfuzzer</code>单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如<code>asan</code>应该被使用。</p> +<p>可执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build +</span></span></code></pre></td></tr></table> +</div> +</div><p>之后,测试应该被定位在<code>out/linux-x64-tests-lang-asan-libfuzzer/tests/</code>。</p> +<h4 id="ossfuzz的配置"><code>ossfuzz</code>的配置 +</h4><p><code>ossfuzz</code>配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如<code>$CFLAGS</code>、<code>$CXXFLAGS</code>和<code>$lib_fuzzing_engine</code>。</p> +<p>你可能需要<code>libfuzzer</code>+<code>asan</code>的构建来代替本地测试。</p> +<h2 id="构建自定义配置">构建自定义配置 +</h2><p>构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:</p> +<ul> +<li>将<code>--args</code>选项传递给<code>gn gen</code>。</li> +<li>在输出目录上运行<code>gn args</code>。</li> +<li>编辑输出目录下的<code>args.gn</code>。</li> +</ul> +<p>要配置一个新的构建或编辑现有构建的参数,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn args out/custom +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><p>两个关键的内置构建参数是 <code>target_os</code> 和 <code>target_cpu</code>,它们分别控制构建的操作系统和CPU。</p> +<p>要查看所有可用的构建参数的帮助,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/custom +</span></span><span class="line"><span class="cl">gn args --list out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="构建实例">构建实例 +</h2><p>你可以通过两种方式构建例子。</p> +<h3 id="1将例子作为独立的项目来构建">1.将例子作为独立的项目来构建 +</h3><p>要把例子作为单独的项目来构建,在Matter的<code>third_party directory</code>,运行下面的命令,输入正确的路径到例子的正确路径(这里是 &ldquo;chip-shell&rdquo;):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd examples/shell +</span></span><span class="line"><span class="cl">gn gen out/debug +</span></span><span class="line"><span class="cl">ninja -C out/debug +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在顶层建立实例">2.在顶层建立实例 +</h3><p>你可以在Matter项目的顶层构建例子。请看下面的<code>统一构建</code>一节了解详情。</p> +<h2 id="统一构建">统一构建 +</h2><p>要构建一个近似于连续构建集的统一配置,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34;&#39; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/unified all +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。</p> +<p>这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/unified host_gcc +</span></span><span class="line"><span class="cl">ninja -C out/unified check_host_gcc +</span></span></code></pre></td></tr></table> +</div> +</div><p>用配置的名称替换<code>host_gcc</code>,它可以在根目录下的 &ldquo;BUILD.gn &ldquo;中找到。</p> +<p>你也可以用参数对生成的配置进行微调。比如说</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34; enable_host_clang_build=false&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><p>完整的列表请参见根目录<code>BUILD.gn</code>。</p> +<p>在统一的构建中,目标有多个实例,需要通过添加通过添加<code>(toolchain)</code>后缀来区分。使用<code>gn ls out/debug</code>来列出所有的目标实例。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">desc</span> <span class="n">out</span><span class="o">/</span><span class="n">unified</span> <span class="s1">&#39;//src/controller(//build/toolchain/host:linux_x64_clang)&#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 +必须作为构建参数提供。例如,要添加 <code>Simplelink cc13x2_26x2</code> 例子到统一构建中,安装<a class="link" href="https://www.ti.com/tool/SYSCONFIG" target="_blank" rel="noopener" +>SysConfig</a> 并添加以下构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#34;target_os=\&#34;all\&#34; enable_ti_simplelink_builds=true &gt; ti_sysconfig_root=\&#34;/path/to/sysconfig\&#34;&#34; +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<h2 id="获得帮助">获得帮助 +</h2><p>GN集成了帮助,你可以通过<code>gn help</code>命令访问。</p> +<p>请确保查看以下推荐的主题:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn帮助执行</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="err">语法</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="n">toolchain</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可参见 <a class="link" href="https://gn.googlesource.com/gn/&#43;/master/docs/quick_start.md" target="_blank" rel="noopener" +>快速入门指南</a>。</p> +<h2 id="自省">自省 +</h2><p>GN有各种自省工具来帮助你检查构建配置。下面的例子以<code>out/host</code>输出目录为例:</p> +<ul> +<li> +<p>显示一个输出目录中的所有目标:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn ls out/host +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示所有将被构建的文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn output out/host &#39;*&#39; +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示配置的目标的GN表示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/inet --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>将整个构建的GN表示转为JSON格式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host/ &#39;*&#39; --all --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示依赖关系树:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //:all deps --tree --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>查找依赖性路径:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn path out/host //src/transport/tests:test //src/system +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>列出与`libCHIP&rsquo;连接的有用信息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/lib include_dirs +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib defines +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib outputs +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 一切都是JSON格式 +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h2 id="覆盖范围">覆盖范围 +</h2><p>代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。</p> +<p>运行以下命令来启动该脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build_coverage.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> -c, --code 指定收集覆盖数据的范围。 +</span></span><span class="line"><span class="cl"> core&#34;:从Matter SDK的核心堆栈中收集覆盖数据。--default +</span></span><span class="line"><span class="cl"> clusters&#34;:从Matter SDK中的cluster实现中收集覆盖数据。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;:收集Matter SDK的覆盖数据。 +</span></span><span class="line"><span class="cl"> -t, --tests 指定哪些工具来运行覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;unit&#39;: 运行单元测试来驱动覆盖率检查。--default +</span></span><span class="line"><span class="cl"> &#39;yaml&#39;: 运行yaml测试来驱动覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;: 运行单元和yaml测试来驱动覆盖率检查。 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): <a class="link" href="https://matter-build-automation.ue.r.appspot.com/" target="_blank" rel="noopener" +>matter coverage</a>。</p> +<h2 id="维护事项">维护事项 +</h2><p>如果你对GN构建系统做了任何改变,下一次构建会自动重新生成<code>ninja</code>文件。不需要做任何事情。</p>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/Sat, 06 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/<img src="https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover.jpg" alt="Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)" /><h1 id="esp-matter环境下的应用实践">esp-matter环境下的应用实践 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><p>请确保你本地已经配置好 <code>esp-idf</code> 及<code>esp-matter</code>环境,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130484975?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter开发环境搭建</a></p> +<h2 id="设置环境变量">设置环境变量 +</h2><h3 id="1esp-idf">1.ESP-IDF +</h3><p>根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041609281.png" +loading="lazy" +alt="image-20230504160909004" +></p> +<h3 id="2esp-matter">2.ESP-Matter +</h3><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>Linux</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>macOS</a></li> +</ul> +<p>由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>此处</a></p> +<p>在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>准备编译matter所需环境。注:如切换了其他分支需要重新运行</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060133538.png" +loading="lazy" +alt="image-20230506013329415" +></p> +<p>激活编译matter环境</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041611578.png" +loading="lazy" +alt="image-20230504161123505" +></p> +<h2 id="matter-example编译下载">Matter Example编译下载 +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2选择esp设备">2.选择esp设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>初次执行这个命令发生了如下报错:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">AttributeError</span><span class="p">:</span> <span class="err">&#39;</span><span class="n">HTTPResponse</span><span class="err">&#39;</span> <span class="n">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="err">&#39;</span><span class="n">strict</span><span class="err">&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在GitHub上参考此<a class="link" href="https://github.com/espressif/esp-idf/issues/11340" target="_blank" rel="noopener" +>issue</a>,并执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时重新执行esp-matter安装脚本:</p> +<p>由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此<a class="link" href="https://github.com/kurisaW/Summer-of-Open-Source/issues/7" target="_blank" rel="noopener" +>issue</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="p">.</span><span class="n">environment</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后回到示例工程下继续执行esp设备选择</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时发生了新的错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060221146.png" +loading="lazy" +alt="image-20230506022134054" +></p> +<p>由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">rm</span> <span class="o">-</span><span class="n">r</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span><span class="o">/</span><span class="n">build</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后成功解决问题:</p> +<p><img src="https://user-images.githubusercontent.com/98592772/236539480-35af78e1-382f-4092-a25b-fb2a09004d0a.png" +loading="lazy" +alt="b372338ad9384db034000d7839549b5" +></p> +<h3 id="3编译工程">3.编译工程 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060250998.png" +loading="lazy" +alt="image-20230506025001282" +></p> +<h3 id="4sdk烧写">4.SDK烧写 +</h3><p>第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">erase_flash</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060252819.png" +loading="lazy" +alt="image-20230506025047817" +></p> +<p>烧录程序并打开串口监视</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>可以看到烧录进度:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060251334.png" +loading="lazy" +alt="image-20230506025133178" +></p> +<p>包括串口监视器的提示信息,同时执行以下命令可退出串口监视:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">CTRL</span> <span class="o">+</span> <span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060254172.png" +loading="lazy" +alt="image-20230506025401001" +></p> +<p>那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。</p> +<hr> +<p>参考链接:</p> +<p><a class="link" href="https://blog.csdn.net/hydfxy2018/article/details/122041168?spm=1001.2101.3001.6650.11&amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;utm_relevant_index=12" target="_blank" rel="noopener" +>Matter Over Wifi 例程体验(CHIP Over Wifi)</a></p> +<p><a class="link" href="https://blog.csdn.net/weixin_40209493/article/details/125814311?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168324979316800211536064%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=168324979316800211536064&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-125814311-null-null.142%5ev86%5econtrol_2,239%5ev2%5einsert_chatgpt&amp;utm_term=matter%E6%8A%A5%E9%94%99&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>ESP-Matter 环境测试</a></p> +<p><a class="link" href="https://blog.csdn.net/puweiqi/article/details/129474079?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;utm_relevant_index=3" target="_blank" rel="noopener" +>matter搭建环境</a></p> +<p><a class="link" href="https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html" target="_blank" rel="noopener" +>https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html</a></p>【Matter】esp-matter开发环境搭建https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【Matter】esp-matter开发环境搭建" /><h1 id="esp-matter开发环境搭建">esp-matter开发环境搭建 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><h3 id="1ubuntu2204磁盘容量不小于80g">1.Ubuntu22.04(磁盘容量不小于80G) +</h3><h3 id="2科学上网环境">2.科学上网环境 +</h3><p>由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。</p> +<p>参考链接:<a class="link" href="https://kurisaw.github.io/p/%e7%bb%8f%e9%aa%8c%e5%88%86%e4%ba%ablinux-%e7%8e%af%e5%a2%83%e4%b8%8bv2ray%e7%9a%84%e4%bd%bf%e7%94%a8/" target="_blank" rel="noopener" +>【经验分享】Linux 环境下v2ray的使用</a></p> +<h2 id="esp-idf-开发环境搭建">esp-idf 开发环境搭建 +</h2><h3 id="1esp-idf-依赖环境安装">1.ESP-IDF 依赖环境安装 +</h3><blockquote> +<p>参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:</p> +<ul> +<li>Problem1:执行 git submodule 速度慢</li> +<li>Problem2:执行install.sh 速度慢</li> +</ul> +<p>所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。</p> +<h3 id="2problem1-solution">2.Problem1 solution +</h3><p>首先使用递归克隆命令克隆整个仓库到文件夹下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-idf.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span> <span class="o">--</span><span class="n">recursive</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:</p> +<ul> +<li>jihu-mirror 使用(推荐)</li> +<li>submodule-update 使用(不推荐)</li> +</ul> +<h4 id="21--jihu-mirror-使用推荐">2.1 jihu-mirror 使用(推荐) +</h4><ul> +<li>Step 1:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-gitee-tools.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Step 2:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 使用如下命令将仓库的 URL 进行替换: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">url</span><span class="p">.</span><span class="nl">https</span><span class="p">:</span><span class="c1">//jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>当我们使用命令 <code>git clone https://github.com/espressif/esp-idf</code> 时,默认的 URL <code>https://github.com/espressif/esp-idf</code> 将被自动替换成 <code>https://jihulab.com/esp-mirror/espressif/esp-idf</code>。</p> +<ul> +<li>Step 3:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 启用镜像URL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">set</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用命令 <code>./jihu-mirror.sh unset</code> 恢复,不使用镜像的 URL。</p> +<ul> +<li>Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recursive https://github.com/espressif/esp-idf.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然如果不想使用镜像的URL可以使用如下命令进行恢复:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">unset</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22--submodule-update-使用不推荐">2.2 submodule-update 使用(不推荐) +</h4><ul> +<li> +<p>Step 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">gitee</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">EspressifSystems</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">.</span><span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>Step 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 仅克隆 esp-idf,不包含子模块 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-idf.git +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<ul> +<li>Step 3:</li> +</ul> +<p>可以有两种方式来更新 submodules。</p> +<ul> +<li> +<p>方式一</p> +<p>进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">EGT_PATH</span><span class="o">=$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入 esp-idf 目录执行 submodule-update.sh 脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd esp-idf +</span></span><span class="line"><span class="cl">$EGT_PATH/submodule-update.sh +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>方式二</p> +<p><code>submodule-update.sh</code> 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:<code>submodule-update.sh PATH_OF_PROJ</code>。</p> +<p>假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="o">./</span><span class="n">submodule</span><span class="o">-</span><span class="n">update</span><span class="o">.</span><span class="n">sh</span> <span class="o">~/</span><span class="n">git</span><span class="o">/</span><span class="n">esp32</span><span class="o">-</span><span class="n">sdk</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果要更新其他工程,可以同样方式。</p> +</li> +</ul> +<blockquote> +<p>值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!</p> +</blockquote> +<h3 id="3problem2-solution">3.Problem2 solution +</h3><p>下面说第二个问题:执行./install.sh速度慢的问题</p> +<p>在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 <code>IDF_GITHUB_ASSETS</code> 的环境变量来指定这个地址。在设置了 <code>IDF_GITHUB_ASSETS</code> 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">export</span> <span class="n">IDF_GITHUB_ASSETS</span><span class="o">=</span><span class="s">&#34;dl.espressif.com/github_assets&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后再执行安装命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这还报了一个错误</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041247286.png" +loading="lazy" +alt="image-20230504124717772" +></p> +<p>我们根据提示安装<code>python3.10-venv</code>,并再次执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="mf">.10</span><span class="o">-</span><span class="n">venv</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041249721.png" +loading="lazy" +alt="image-20230504124913620" +></p> +<p>至此,esp-idf 的安装工具就告一段落了。</p> +<h2 id="esp-matter开发环境搭建-1">esp-matter开发环境搭建 +</h2><blockquote> +<p>参考:<a class="link" href="https://github.com/espressif/esp-matter" target="_blank" rel="noopener" +>【乐鑫 Matter SDK GitHub】</a></p> +</blockquote> +<p>**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:<code>./jihu-mirror.sh unset</code>取消esp镜像!! **</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-matter.git +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git submodule update --init --recursive +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错&hellip;</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): started +</span></span><span class="line"><span class="cl"> error: subprocess-exited-with-error +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> × python setup.py bdist_wheel did not run successfully. +</span></span><span class="line"><span class="cl"> │ exit code: 1 +</span></span><span class="line"><span class="cl"> ╰─&gt; See above for output. +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> note: This error originates from a subprocess, and is likely not a problem with pip. +</span></span><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): finished with status &#39;error&#39; +</span></span><span class="line"><span class="cl"> ERROR: Failed building wheel for pycryptodome +</span></span><span class="line"><span class="cl"> Running setup.py clean for pycryptodome +</span></span><span class="line"><span class="cl"> Building wheel for gevent (pyproject.toml): started +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ...... +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们查看<code>install.sh</code>文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">basedir</span><span class="o">=</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">ESP_MATTER_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="nb">pwd</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">MATTER_PATH</span><span class="o">=</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">export</span> ESP_MATTER_PATH +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Running Matter Setup&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/scripts/bootstrap.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Run the zap_download.py and extract the path of installed binary</span> +</span></span><span class="line"><span class="cl"><span class="c1"># eg output before cut: &#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># output after cut: zap/zap-v2023.03.06-nightly</span> +</span></span><span class="line"><span class="cl"><span class="c1"># TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged</span> +</span></span><span class="line"><span class="cl"><span class="nv">zap_path</span><span class="o">=</span><span class="sb">`</span>python3 <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --sdk-root <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --extract-root .zap 2&gt;/dev/null <span class="p">|</span> cut -d<span class="o">=</span> -f2<span class="sb">`</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Check whether the download is successful.</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="nv">$zap_path</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Failed to install zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"> deactivate +</span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span><span class="s2">/.zap&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> rm -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl">mkdir <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl">mv <span class="nv">$zap_path</span>/* <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/ +</span></span><span class="line"><span class="cl">rm -r <span class="nv">$zap_path</span> +</span></span><span class="line"><span class="cl">chmod +x <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/zap-cli +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Building host tools&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">gn --root<span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">&#34;</span> gen <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl">ninja -C <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Host tools built at: </span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">/out/host&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Exit Matter environment&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">deactivate +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for mfg_tool&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/tools/mfg_tool/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for Matter&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;All done! You can now run:&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34; . </span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">/export.sh&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install build-essential python3-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pkg-config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" +loading="lazy" +alt="image-20230504145216015" +></a></p> +<p>接着在安装<code>zap-cli</code>的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./install.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" +loading="lazy" +alt="image-20230504150238105" +></a></p> +<p>最后看到<code>All done!</code>即代表环境安装成功!</p> +<p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" +loading="lazy" +alt="image-20230504153243388" +></a></p> +<p>至此,esp-matter开发环境搭建成功!</p>【经验分享】Linux环境下v2ray的使用https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/cover.jpg" alt="Featured image of post 【经验分享】Linux环境下v2ray的使用" /><h1 id="linux-环境下v2ray的使用">Linux 环境下v2ray的使用 +</h1><hr> +<blockquote> +<p>v2ray官方文档:<a class="link" href="https://v2raya.org/" target="_blank" rel="noopener" +>https://v2raya.org/</a></p> +</blockquote> +<h2 id="curl安装">curl安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">apt-get purge libcurl4 +</span></span><span class="line"><span class="cl">apt-get install curl +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray镜像脚本安装">v2ray镜像脚本安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">curl</span> <span class="o">-</span><span class="n">Ls</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.v2raya.org/go.sh | sudo bash +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041040498.png" +loading="lazy" +alt="image-20230504104013149" +></p> +<p>出现该提示信息则表示安装成功:<code>info: V2Ray v5.4.1 is installed.</code></p> +<p>接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">disable</span> <span class="n">v2ray</span> <span class="o">--</span><span class="n">now</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray软件安装">v2ray软件安装 +</h2><blockquote> +<p>仓库release地址:<a class="link" href="https://github.com/v2rayA/v2rayA/releases" target="_blank" rel="noopener" +>https://github.com/v2rayA/v2rayA/releases</a></p> +</blockquote> +<p>选择合适自己 Linux 内核架构,可以使用<code>dpkg --print-architecture</code>查看</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041050162.png" +loading="lazy" +alt="image-20230504105029122" +></p> +<p>这里我选择``下载到 Linux 共享文件夹</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041052416.png" +loading="lazy" +alt="image-20230504105226313" +></p> +<p>将共享文件夹下的<code>installer_debian_amd64_2.0.5.deb</code>文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041054352.png" +loading="lazy" +alt="image-20230504105440300" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041053522.png" +loading="lazy" +alt="image-20230504105340371" +></p> +<h2 id="启动v2raya进程">启动v2raya进程 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">start</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="设置开机自启动">设置开机自启动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">enable</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray使用">v2ray使用 +</h2><p>打开火狐浏览器,输入 http://localhost:2017/</p> +<p>输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041058629.png" +loading="lazy" +alt="image-20230504105825544" +></p> +<p>导入我们的机场订阅地址</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041100916.png" +loading="lazy" +alt="image-20230504105925321" +></p> +<p>选择想要使用的节点后,点击 Ready</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041106172.png" +loading="lazy" +alt="image-20230504110635073" +></p> +<h2 id="v2ray-settings">v2ray Settings +</h2><p>我们点击网页上右上角的Setting,进行如下修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041110129.png" +loading="lazy" +alt="image-20230504111011073" +></p> +<h2 id="测试">测试 +</h2><p>至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041111183.png" +loading="lazy" +alt="image-20230504111116983" +></p>【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div>Github同步Gitee镜像仓库自动化脚本https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/Tue, 11 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover.jpg" alt="Featured image of post Github同步Gitee镜像仓库自动化脚本" /><h1 id="github同步gitee镜像仓库自动化脚本">Github同步Gitee镜像仓库自动化脚本 +</h1><hr> +<h2 id="前言">前言 +</h2><p>在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。</p> +<h2 id="什么是hub-mirror-action">什么是Hub Mirror Action? +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111537579.png" +loading="lazy" +alt="image-20230411153729450" +></p> +<h3 id="1介绍">1.介绍 +</h3><p><a class="link" href="https://github.com/marketplace/actions/hub-mirror-action" target="_blank" rel="noopener" +>Hub Mirror Action</a>是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。</p> +<h3 id="2用法">2.用法 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Mirror the Github organization repos to Gitee.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># src_account_type: org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># dst_account_type: org</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:详细使用案例请查看官方仓库 <a class="link" href="https://github.com/Yikun/hub-mirror-action" target="_blank" rel="noopener" +>https://github.com/Yikun/hub-mirror-action</a></p> +<h2 id="配置步骤">配置步骤 +</h2><h3 id="1生成密钥对">1.生成密钥对 +</h3><p>我们先在本地使用git命令行打开终端,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ssh</span><span class="o">-</span><span class="n">keygen</span> <span class="o">-</span><span class="n">t</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">f</span> <span class="o">~/</span><span class="n">Documents</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">key</span><span class="o">/</span><span class="n">id_rsa</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注:请确保文件夹<code>~/Documents/ssh-key/</code>存在,当然你也可以选择放置在其他地方</p> +<p>过程中一路回车即可,注意不要设置密码。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111543237.png" +loading="lazy" +alt="image-20230411154330166" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111551053.png" +loading="lazy" +alt="image-20230411155124878" +></p> +<h3 id="2github私钥配置">2.GitHub私钥配置 +</h3><p>首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111547966.png" +loading="lazy" +alt="image-20230411154716849" +></p> +<ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_PRIVATE_KEY</code>的secret,值为我们之前生成的密钥对中的私钥(id_rsa)</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111553202.png" +loading="lazy" +alt="image-20230411155314101" +></p> +<h3 id="3gitee公钥配置">3.Gitee公钥配置 +</h3><p>我们打开Gitee账号,进入<code>Settings-&gt;安全设置-&gt;SSH公钥</code></p> +<p>添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111558684.png" +loading="lazy" +alt="image-20230411155846562" +></p> +<h3 id="4gitee生成私人令牌">4.Gitee生成私人令牌 +</h3><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111559999.png" +loading="lazy" +alt="image-20230411155958898" +></p> +<p>令牌名称随意,同时复制生成的令牌值。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111601466.png" +loading="lazy" +alt="image-20230411160127393" +></p> +<h3 id="5github绑定gitee令牌">5.Github绑定Gitee令牌 +</h3><ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_TOKEN</code>的secret,值为Gitee生成的令牌值</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111603849.png" +loading="lazy" +alt="image-20230411160340721" +></p> +<h3 id="6编写ci脚本">6.编写CI脚本 +</h3><p>将<code>ci_bot</code>仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="n">ci_bot</span><span class="o">/</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="p">.</span><span class="n">github</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">workflows</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">Sync</span><span class="p">.</span><span class="n">yml</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>Sync.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">push, delete, create ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出后,将本次修改push到远端仓库。</p> +<p>查看Action运行情况:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111611887.png" +loading="lazy" +alt="image-20230411161143741" +></p> +<h3 id="7多仓库同步推送">7.多仓库同步推送 +</h3><p>如果你想同时同步多个仓库,只需要完成如下修改</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">static_list 默认为&#39;&#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111633375.png" +loading="lazy" +alt="image-20230411163307283" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111631352.png" +loading="lazy" +alt="image-20230411163135259" +></p> +<h3 id="8定时运行脚本">8.定时运行脚本 +</h3><p>为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:</p> +<p>修改Sync.yml文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 0 * * *&#39;</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">delete</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">create</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111731377.png" +loading="lazy" +alt="image-20230411173142865" +></p> +<h2 id="总结">总结 +</h2><p>通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。</p>【网络编程】OSI七层模型&TCPIP四层模型https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/<img src="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover.jpg" alt="Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型" /><h2 id="osi七层模型">OSI七层模型 +</h2><p>七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。</p> +<h4 id="1物理层">1.物理层 +</h4><p><code>建立、维护、断开物理连接。</code>(由底层网络定义协议)</p> +<p>机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。</p> +<p>应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。</p> +<h4 id="2数据链路层">2.数据链路层 +</h4><p><code>建立逻辑连接、进行硬件地址寻址、差错校验等功能。</code>(由底层网络定义协议)</p> +<p>将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)</p> +<h4 id="3网络层">3.网络层 +</h4><p><code>进行逻辑地址寻址,实现不同网络之间的路径选择。</code></p> +<p>控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)</p> +<h4 id="4传输层">4.传输层 +</h4><p><code>定义传输数据的协议端口号,以及流控和差错校验。</code> +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层</p> +<h4 id="5会话层">5.会话层 +</h4><p><code>建立、管理、终止会话。</code>(在五层模型里面已经合并到了应用层)</p> +<p>不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)</p> +<h4 id="6表示层">6.表示层 +</h4><p><code>数据的表示、安全、压缩。</code>(在五层模型里面已经合并到了应用层)</p> +<p>信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)</p> +<h4 id="7应用层">7.应用层 +</h4><p><code>网络服务与最终用户的一个接口</code></p> +<p>各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)</p> +<hr> +<h2 id="tcpip-四层模型">TCP/IP 四层模型 +</h2><p>TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是<strong>指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇</strong>, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304101020851.png" +loading="lazy" +alt="20201028134158932" +></p> +<p>TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示</p> +<h4 id="1应用层">1.应用层 +</h4><p><code>应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。</code></p> +<ul> +<li>应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次</li> +<li>对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议</li> +<li>应用层还能加密、解密、格式化数据</li> +<li>应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源</li> +</ul> +<h4 id="2传输层">2.传输层 +</h4><p><code>作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用</code></p> +<h4 id="3网络层-1">3.网络层 +</h4><p><code>网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能</code></p> +<h4 id="4网络接口层">4.网络接口层 +</h4><p><code>在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路</code></p>Wireshark网络抓包教程https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover.jpg" alt="Featured image of post Wireshark网络抓包教程" /><blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/HarveyH/article/details/113731485" target="_blank" rel="noopener" +>转自:WireShark 抓包使用教程&ndash;详细</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:</p> +<p>1、Wireshark软件下载和安装以及Wireshark主界面介绍。</p> +<p>2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。</p> +<p>3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。</p> +<h2 id="wireshark软件安装">Wireshark软件安装 +</h2><p>软件下载路径:<a class="link" href="https://www.wireshark.org/" target="_blank" rel="noopener" +>wireshark官网</a>。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。</p> +<p>如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:<a class="link" href="http://www.win10pcap.org/download/" target="_blank" rel="noopener" +>win10pcap兼容性安装包</a></p> +<h2 id="wireshark-开始抓包示例"><strong>Wireshark 开始抓包示例</strong> +</h2><p>先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。</p> +<p>1、打开wireshark 2.6.5,主界面如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102042369.png" +loading="lazy" +alt="image-20230410204240214" +></p> +<p>2、选择菜单栏上Capture -&gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043634.png" +loading="lazy" +alt="image-20230410204301558" +></p> +<p>3、wireshark启动后,wireshark处于抓包状态中。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043120.png" +loading="lazy" +alt="image-20230410204330881" +></p> +<p>4、执行需要抓包的操作,如ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>。</p> +<p>5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043973.png" +loading="lazy" +alt="image-20230410204349768" +></p> +<p>5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。</p> +<h2 id="wireshakr抓包界面">Wireshakr抓包界面 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044121.png" +loading="lazy" +alt="image-20230410204417023" +></p> +<p>说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --&gt; Coloring Rules。如下所示</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044221.png" +loading="lazy" +alt="image-20230410204435065" +></p> +<p><strong>WireShark 主要分为这几个界面</strong></p> +<p>1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --&gt; Display Filters。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045496.png" +loading="lazy" +alt="image-20230410204500320" +></p> +<p>2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045343.png" +loading="lazy" +alt="image-20230410204525166" +></p> +<p>3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为</p> +<p>(1)Frame: 物理层的数据帧概况</p> +<p>(2)Ethernet II: 数据链路层以太网帧头部信息</p> +<p>(3)Internet Protocol Version 4: 互联网层IP包头部信息</p> +<p>(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP</p> +<p>(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045382.png" +loading="lazy" +alt="image-20230410204540297" +></p> +<p><strong>TCP包的具体内容</strong></p> +<p>从下图可以看到wireshark捕获到的TCP包中的每个字段。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045329.png" +loading="lazy" +alt="image-20230410204557194" +></p> +<p>4. Dissector Pane(数据包字节区)。</p> +<h2 id="wireshark过滤器设置">Wireshark过滤器设置 +</h2><p>初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。</p> +<p>(1)抓包过滤器</p> +<p>捕获过滤器的菜单栏路径为Capture --&gt; Capture Filters。用于<strong>在抓取数据包前设置。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046204.png" +loading="lazy" +alt="image-20230410204620124" +></p> +<p>如何使用?可以在抓取数据包前设置如下。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046995.png" +loading="lazy" +alt="image-20230410204653927" +></p> +<p>ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047470.png" +loading="lazy" +alt="image-20230410204717268" +></p> +<p>(2)显示过滤器</p> +<p>显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047185.png" +loading="lazy" +alt="image-20230410204734985" +></p> +<p>执行ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取的数据包列表如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047584.png" +loading="lazy" +alt="image-20230410204753507" +></p> +<p>观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048361.png" +loading="lazy" +alt="image-20230410204815301" +></p> +<p>上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。</p> +<p><strong>wireshark过滤器表达式的规则</strong></p> +<p>1、抓包过滤器语法和实例</p> +<p>抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&amp;&amp; 与、|| 或、!非)</p> +<p>(1)协议过滤</p> +<p>比较简单,直接在抓包过滤框中直接输入协议名即可。</p> +<p>TCP,只显示TCP协议的数据包列表</p> +<p>HTTP,只查看HTTP协议的数据包列表</p> +<p>ICMP,只显示ICMP协议的数据包列表</p> +<p>(2)IP过滤</p> +<p>host 192.168.1.104</p> +<p>src host 192.168.1.104</p> +<p>dst host 192.168.1.104</p> +<p>(3)端口过滤</p> +<p>port 80</p> +<p>src port 80</p> +<p>dst port 80</p> +<p>(4)逻辑运算符&amp;&amp; 与、|| 或、!非</p> +<p>src host 192.168.1.104 &amp;&amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包</p> +<p>host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包</p> +<p>!broadcast 不抓取广播数据包</p> +<p>2、显示过滤器语法和实例</p> +<p>(1)比较操作符</p> +<p>比较操作符有== 等于、!= 不等于、&gt; 大于、&lt; 小于、&gt;= 大于等于、&lt;=小于等于。</p> +<p>(2)协议过滤</p> +<p>比较简单,直接在Filter框中直接输入协议名即可。<strong>注意:协议名称需要输入小写。</strong></p> +<p>tcp,只显示TCP协议的数据包列表</p> +<p>http,只查看HTTP协议的数据包列表</p> +<p>icmp,只显示ICMP协议的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048252.png" +loading="lazy" +alt="image-20230410204852057" +></p> +<p>(3) ip过滤</p> +<p>ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表</p> +<p>ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表</p> +<p>ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049772.png" +loading="lazy" +alt="image-20230410204937591" +></p> +<p>(4)端口过滤</p> +<p>tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。</p> +<p>tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。</p> +<p>tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049752.png" +loading="lazy" +alt="image-20230410204953546" +></p> +<p>(5) Http模式过滤</p> +<p>http.request.method==&ldquo;GET&rdquo;, 只显示HTTP GET方法的。</p> +<p>(6)逻辑运算符为 and/or/not</p> +<p>过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050123.png" +loading="lazy" +alt="image-20230410205019907" +></p> +<p>(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050553.png" +loading="lazy" +alt="image-20230410205039366" +></p> +<p>右键单击选中后出现如下界面</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050685.png" +loading="lazy" +alt="image-20230410205054595" +></p> +<p>选中Select后在过滤器中显示如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051573.png" +loading="lazy" +alt="image-20230410205109402" +></p> +<p>后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含&quot;abcd&quot;内容的数据流。<strong>包含的关键词是contains 后面跟上内容。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051902.png" +loading="lazy" +alt="image-20230410205121718" +></p> +<p>看到这, 基本上对wireshak有了初步了解。</p> +<h2 id="wireshark抓包分析tcp三次握手">Wireshark抓包分析TCP三次握手 +</h2><p>(1)TCP三次握手连接建立过程</p> +<p>Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;</p> +<p>Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;</p> +<p>Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051845.png" +loading="lazy" +alt="image-20230410205135665" +></p> +<p>(2)wireshark抓包获取访问指定服务端数据包</p> +<p>Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。</p> +<p>Step2:使用ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取IP。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051433.png" +loading="lazy" +alt="image-20230410205150253" +></p> +<p>Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052925.png" +loading="lazy" +alt="image-20230410205200760" +></p> +<p>图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。</p> +<p><strong>第一次握手数据包</strong></p> +<p>客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052226.png" +loading="lazy" +alt="image-20230410205215079" +></p> +<p>数据包的关键属性如下:</p> +<p>SYN :标志位,表示请求建立连接</p> +<p>Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据</p> +<p>Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据</p> +<p><strong>第二次握手的数据包</strong></p> +<p>服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052307.png" +loading="lazy" +alt="image-20230410205230236" +></p> +<p>数据包的关键属性如下:</p> +<p>[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK</p> +<p>Seq = 0 :初始建立值为0,表示当前还没有发送数据</p> +<p>Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)</p> +<p><strong>第三次握手的数据包</strong></p> +<p>客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052080.png" +loading="lazy" +alt="image-20230410205245006" +></p> +<p>数据包的关键属性如下:</p> +<p>ACK :标志位,表示已经收到记录</p> +<p>Seq = 1 :表示当前已经发送1个数据</p> +<p>Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。</p> +<p>就这样通过了TCP三次握手,建立了连接。开始进行数据交互</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053540.png" +loading="lazy" +alt="image-20230410205305433" +></p> +<p>下面针对数据交互过程的数据包进行一些说明:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053537.png" +loading="lazy" +alt="image-20230410205320467" +></p> +<p>数据包的关键属性说明</p> +<p>Seq: 1</p> +<p>Ack: 1: 说明现在共收到1字节数据</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053985.png" +loading="lazy" +alt="image-20230410205335911" +></p> +<p>Seq: 1<br> +Ack: 951: 说明现在服务端共收到951字节数据</p> +<p>在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053340.png" +loading="lazy" +alt="image-20230410205349152" +></p> +<p>其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。</p> +<h2 id="wireshark分析常用操作">Wireshark分析常用操作 +</h2><p>调整数据包列表中时间戳显示格式。调整方法为View --&gt;Time Display Format --&gt; Date and Time of Day。调整后格式如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102054848.png" +loading="lazy" +alt="image-20230410205401641" +></p>RT-Thread内核宏定义详解(rtdef.h)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/Sun, 09 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/cover.jpg" alt="Featured image of post RT-Thread内核宏定义详解(rtdef.h)" /><h4 id="1rt-thread版本信息">1.RT-Thread版本信息 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread version information */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_VERSION 4 </span><span class="cm">/**&lt; major version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SUBVERSION 1 </span><span class="cm">/**&lt; minor version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_REVISION 1 </span><span class="cm">/**&lt; revise version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread version */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>使用方法:可用于bsp指定RT-Thread版本</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#if (RTTHREAD_VERSION &gt;= RT_VERSION_CHECK(4, 1, 0) */ +</span></span><span class="line"><span class="cl">#define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \ +</span></span><span class="line"><span class="cl"> (minor * 100) + revise) +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2rt-thrad基础数据类型定义">2.RT-Thrad基础数据类型定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread basic data type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_ARCH_DATA_TYPE </span><span class="cm">/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC </span><span class="cm">/* 用于控制是否使用标准C库函数 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">int8_t</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int16_t</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int32_t</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint8_t</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint16_t</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint32_t</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int64_t</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint64_t</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">size_t</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">char</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">short</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">int</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef ARCH_CPU_64BIT </span><span class="cm">/* 判断当前程序运行的CPU架构是否为64位 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* ARCH_CPU_64BIT */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_ARCH_DATA_TYPE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int</span> <span class="kt">rt_bool_t</span><span class="p">;</span> <span class="cm">/**&lt; boolean type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">rt_base_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit CPU related date type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_ubase_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit unsigned CPU related data type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_err_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for error number */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_time_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for time stamp */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_tick_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for tick count */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_flag_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for flags */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_ubase_t</span> <span class="kt">rt_dev_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for device */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_off_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for offset */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* boolean type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TRUE 1 </span><span class="cm">/**&lt; boolean true */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_FALSE 0 </span><span class="cm">/**&lt; boolean fails */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* null pointer definition */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_NULL 0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p><code>rt_base_t</code>:为了使代码可以<strong>在不同的CPU上移植并保持向后兼容性</strong>。<code>long</code>类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用<code>rt_base_t</code>代替<code>long</code>可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)</p> +</li> +<li> +<p><code>rt_err_t</code>:代表<strong>错误码</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_time_t</code>:代表<strong>时间戳</strong>的数据类型,这里使用了<code>rt_uint32_t</code>作为它的别名。<code>rt_uint32_t</code>是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。</p> +</li> +<li> +<p><code>rt_tick_t</code>:代表<strong>系统时钟节拍计数</strong>的数据类型,这里也使用了<code>rt_uint32_t</code>作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对<code>rt_tick_t</code>进行递增操作,从而实现对时间的计数。</p> +</li> +<li> +<p><code>rt_flag_t</code>:代表<strong>标志位</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_dev_t</code>:代表<strong>设备号</strong>的数据类型,这里使用了<code>rt_ubase_t</code>作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。</p> +</li> +<li> +<p><code>rt_off_t</code>:代表<strong>偏移量</strong>的数据类型,这里也使用了之前定义的<code>rt_base_t</code>作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。</p> +</li> +</ul> +<h4 id="3rt-thread基本数据类型的范围">3.RT-Thread基本数据类型的范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of base type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX UINT8_MAX </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX UINT16_MAX </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX UINT32_MAX </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX 0xff </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX 0xffff </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX 0xffffffff </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:此处的<code>UINT8_MAX</code>、<code>UINT16_MAX</code>、<code>UINT32_MAX</code>为编译器预定的宏定义</p> +<h4 id="4rt-thread系统滴答时钟最大计数值">4.RT-Thread系统滴答时钟最大计数值 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TICK_MAX RT_UINT32_MAX </span><span class="cm">/**&lt; Maximum number of tick */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5rt-thread-ipc数据类型范围">5.RT-Thread IPC数据类型范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of ipc type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SEM_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of semaphore .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mutex .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_HOLD_MAX RT_UINT8_MAX </span><span class="cm">/**&lt; Maximum number of mutex .hold */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MB_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mailbox .entry */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MQ_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of message queue .entry */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6rt-thread避免未使用变量警告">6.RT-Thread避免未使用变量警告 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_UNUSED(x) ((void)x) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>**该宏定义表示将变量x强制转换为<code>void</code>类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **</p> +<p>下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。</p> +<p>该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。</p> +<p>在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。</p> +<p>这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* sort code */</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">cmp</span><span class="p">);</span> <span class="c1">// 必须传递一个void*类型参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">b</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就可以避免编译器报“未使用变量a/b”的警告了。</p> +<h4 id="7编译器相关定义">7.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_SECTION(x)</code>:表示<strong>将所修饰的数据/函数放置在指定的section中</strong>,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。</li> +<li><code>RT_USED</code>:表示<strong>告诉编译器保留所修饰的数据/函数</strong>,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。</li> +<li><code>ALIGN(n)</code>:表示<strong>将所修饰的数据/函数按照n字节对齐</strong>,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。</li> +<li><code>RT_WEAK</code>:表示<strong>将所修饰的数据/函数标记为弱引用</strong>,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。</li> +<li><code>rt_inline</code>:表示<strong>将所修饰的函数定义为静态内联函数</strong>,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。</li> +</ul> +<h4 id="8编译器相关定义">8.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* module compiling */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_MODULE +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllimport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllexport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_MODULE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__IAR_SYSTEMS_ICC__) </span><span class="cm">/* for IAR Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) @ x +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __root +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) PRAGMA(data_alignment=n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __weak +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__GNUC__) </span><span class="cm">/* GNU GCC Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* the version of GNU GCC must be greater than 4.x */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__builtin_va_list</span> <span class="n">__gnuc_va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__gnuc_va_list</span> <span class="n">va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define va_start(v,l) __builtin_va_start(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_end(v) __builtin_va_end(v) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_arg(v,l) __builtin_va_arg(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__ADSPBLACKFIN__) </span><span class="cm">/* for VisualDSP++ Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (_MSC_VER) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __declspec(align(n)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TI_COMPILER_VERSION__) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* The way that TI compiler set section is different from other(at least +</span></span></span><span class="line"><span class="cl"><span class="cm"> * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more +</span></span></span><span class="line"><span class="cl"><span class="cm"> * details. */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TASKING__) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used, protect)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((__align(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="cp">#error not supported tool chain +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* __ARMCC_VERSION */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ol> +<li><code>typedef __builtin_va_list __gnuc_va_list</code>: 定义了一个新类型<code>__gnuc_va_list</code>,并使用 <code>__builtin_va_list</code> 进行初始化。<code>__builtin_va_list</code> 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 <code>__builtin_va_list</code> 类型来实现可变参数列表。</li> +<li><code>typedef __gnuc_va_list va_list</code>: 定义了一个名为<code>va_list</code>的新类型,并将其重命名为<code>__gnuc_va_list</code>。</li> +<li><code>#define va_start(v,l) __builtin_va_start(v,l)</code>: 将 <code>va_start()</code> 重命名为 <code>__builtin_va_start()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_start()</code> 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。</li> +<li><code>#define va_end(v) __builtin_va_end(v)</code>: 将 <code>va_end()</code> 重命名为 <code>__builtin_va_end()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_end()</code> 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。</li> +<li><code>#define va_arg(v,l) __builtin_va_arg(v,l)</code>: 将 <code>va_arg()</code> 重命名为 <code>__builtin_va_arg()</code>,并使用 GCC 内建的函数 <code>__builtin_va_arg()</code> 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。</li> +<li><code>#define PRAGMA(x) _Pragma(#x)</code>:将参数<code>x</code>转化为字符串并使用<code>_Pragma()</code>将其作为编译指令执行。<code>_Pragma</code>是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而<code>#pragma</code>则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。</li> +</ol> +<h4 id="9rt-thread错误码定义">9.RT-Thread错误码定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread error code definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_EOK 0 </span><span class="cm">/**&lt; There is no error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ERROR 1 </span><span class="cm">/**&lt; A generic error happens */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ETIMEOUT 2 </span><span class="cm">/**&lt; Timed out */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EFULL 3 </span><span class="cm">/**&lt; The resource is full */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EEMPTY 4 </span><span class="cm">/**&lt; The resource is empty */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOMEM 5 </span><span class="cm">/**&lt; No memory */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOSYS 6 </span><span class="cm">/**&lt; No system */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EBUSY 7 </span><span class="cm">/**&lt; Busy */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EIO 8 </span><span class="cm">/**&lt; IO error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINTR 9 </span><span class="cm">/**&lt; Interrupted system call */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINVAL 10 </span><span class="cm">/**&lt; Invalid argument */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_EOK</code>:表示没有错误。</li> +<li><code>RT_ERROR</code>:表示发生了一般性的错误。</li> +<li><code>RT_ETIMEOUT</code>:表示超时错误。</li> +<li><code>RT_EFULL</code>:表示资源已满。</li> +<li><code>RT_EEMPTY</code>:表示资源为空。</li> +<li><code>RT_ENOMEM</code>:表示内存不足。</li> +<li><code>RT_ENOSYS</code>:表示没有该系统。</li> +<li><code>RT_EBUSY</code>:表示忙碌。</li> +<li><code>RT_EIO</code>:表示输入/输出错误。</li> +<li><code>RT_EINTR</code>:表示中断的系统调用。</li> +<li><code>RT_EINVAL</code>:表示无效的参数。</li> +</ul>【HarmonyOS】小熊派鸿蒙系统搭建https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建" /><h2 id="一bearpi-hm-micro-开发板介绍">一、BearPi-HM Micro 开发板介绍 +</h2><p>BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。</p> +<h2 id="二linux镜像下载">二、Linux镜像下载 +</h2><p>下载官方提供镜像(任选一种方式下载)</p> +<ul> +<li>Ubuntu20.04(大小8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1W0cgtXC5T2bv0lAya7eizA" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA</a> 提取码:1234</li> +<li>Ubuntu18.04(大小4.8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1YIdqlRWRGq_heAfrgQ7EPQ" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ</a> 提取码:1234</li> +</ul> +<h2 id="三bearpi-hm-micro编译环境配置">三、BearPi-HM Micro编译环境配置 +</h2><p>在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置</p> +<h4 id="1首先添加如下镜像源">1.首先添加如下镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /etc/apt/source.list +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 添加中科大源 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2更新镜像源">2.更新镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get update +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3安装依赖库及工具">3.安装依赖库及工具 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">gcc</span> <span class="n">g</span><span class="o">++</span> <span class="n">make</span> <span class="n">zlib</span><span class="o">*</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">e2fsprogs</span> <span class="n">pkg</span><span class="o">-</span><span class="n">config</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">perl</span> <span class="n">bc</span> <span class="n">openssl</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">libelf</span><span class="o">-</span><span class="n">dev</span> <span class="n">libc6</span><span class="o">-</span><span class="n">dev</span><span class="o">-</span><span class="n">amd64</span> <span class="n">binutils</span> <span class="n">binutils</span><span class="o">-</span><span class="n">dev</span> <span class="n">libdwarf</span><span class="o">-</span><span class="n">dev</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">tools</span> <span class="n">mtd</span><span class="o">-</span><span class="n">utils</span> <span class="n">gcc</span><span class="o">-</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabi</span> <span class="n">cpio</span> <span class="n">device</span><span class="o">-</span><span class="n">tree</span><span class="o">-</span><span class="n">compiler</span> <span class="n">net</span><span class="o">-</span><span class="n">tools</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> <span class="n">git</span> <span class="n">vim</span> <span class="n">openjdk</span><span class="o">-</span><span class="mi">11</span><span class="o">-</span><span class="n">jre</span><span class="o">-</span><span class="n">headless</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装hb">4.安装hb +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 安装hb命令 +</span></span><span class="line"><span class="cl">python3 -m pip install --user ohos-build==0.4.3 +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 环境变量配置</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 在.bashrc文件最后一行添加如下代码,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/.</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5测试hb是否安装成功">5.测试hb是否安装成功 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb -h +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071818214.png" +loading="lazy" +alt="image-20230407181805793" +></p> +<h2 id="四安装mkimage工具">四、安装mkimage工具 +</h2><p>首先解释这个工具的用途:<strong>用来制作不压缩或者压缩的多种可启动映象文件。</strong></p> +<h4 id="1新建tools目录">1.新建tools目录 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">~/</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2下载mkimagestm32工具到tools目录并复制到homebearpitools目录下">2.下载mkimage.stm32工具到<code>~/tools</code>目录,并复制到/home/bearpi/tools/目录下 +</h4><ul> +<li><a class="link" href="https://pan.baidu.com/share/init?surl=T2O8luJ0-8g5ZZYdOvWfqQ" target="_blank" rel="noopener" +>mkimage.stm32下载地址</a> 提取码:1234</li> +</ul> +<h4 id="3修改mkimagestm32文件权限">3.修改mkimage.stm32文件权限 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chmod</span> <span class="mi">777</span> <span class="o">~/</span><span class="n">tools</span><span class="o">/</span><span class="n">mkimage</span><span class="o">.</span><span class="n">stm32</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4设置环境变量">4.设置环境变量 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 将下面的代码拷贝至.bashrc文件最后,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/</span><span class="n">tools</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="五bearpi镜像导入vmware">五、bearpi镜像导入VMware +</h2><p>准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-&gt;打开(O),选择我们Linux镜像中的<code>BearPi-HM_Micro_Ubuntu.ovf</code>文件,等待镜像文件的导入,开始登录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">账户:bearpi +</span></span><span class="line"><span class="cl">密码:bearpi +</span></span></code></pre></td></tr></table> +</div> +</div><p>首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-&gt;设置-&gt;网络适配器-&gt;NAT模式</p> +<p>此时打开一个终端,输入ifconfig查看ip</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071852103.png" +loading="lazy" +alt="image-20230407185206621" +></p> +<h2 id="六源码获取">六、源码获取 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mkdir project &amp;&amp; cd project +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七编译代码">七、编译代码 +</h2><p>首先进入到项目文件夹中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi/project/bearpi-hm_micro_small/ +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行如下命令(普通用户模式终端下):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb set +</span></span></code></pre></td></tr></table> +</div> +</div><p>出现<code>[OHOS INFO] Input code path: </code>提示信息后再输入<code>.</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071902001.png" +loading="lazy" +alt="image-20230407190200859" +></p> +<p>我们选择<code>bearpi-hm_micro</code>后回车</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071904137.png" +loading="lazy" +alt="image-20230407190426957" +></p> +<p>输入下面的命令,等待下载程序完成</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb build -t notest --tee -f +</span></span></code></pre></td></tr></table> +</div> +</div><p>当出现<code>build success</code>时,即代表编译成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071916323.png" +loading="lazy" +alt="image-20230407191628183" +></p> +<h2 id="八查看编译出的固件位置">八、查看编译出的固件位置 +</h2><p>当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: <code>/home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro</code> 其中有以下文件是后面烧录系统需要使用的。</p> +<ul> +<li>OHOS_Image.stm32:系统镜像文件</li> +<li>rootfs_vfat.img:根文件系统</li> +<li>userfs_vfat.img:用户文件系统</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071919790.png" +loading="lazy" +alt="image-20230407191938678" +></p> +<p>我们将这三个文件复制到该目录下:<code>/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/</code>,方便后续烧录系统使用</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="n">OHOS_Image</span><span class="o">.</span><span class="n">stm32</span> <span class="n">rootfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="n">userfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">bearpi</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">bearpi</span><span class="o">-</span><span class="n">hm_micro_small</span><span class="o">/</span><span class="n">applications</span><span class="o">/</span><span class="n">BearPi</span><span class="o">/</span><span class="n">BearPi</span><span class="o">-</span><span class="n">HM_Micro</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">download_img</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071929824.png" +loading="lazy" +alt="image-20230407192926584" +></p> +<h2 id="九固件烧录">九、固件烧录 +</h2><h4 id="1准备工作">1.准备工作 +</h4><ul> +<li><a class="link" href="https://www.wch.cn/downloads/CH341SER_EXE.html" target="_blank" rel="noopener" +>CH340驱动</a></li> +<li><a class="link" href="https://www.st.com/en/development-tools/stm32cubeprog.html#get-software" target="_blank" rel="noopener" +>STM32CubeProgramme(v2.4.0+)</a></li> +</ul> +<h4 id="2连接开发板">2.连接开发板 +</h4><p>首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:<a class="link" href="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/" target="_blank" rel="noopener" +>【Linux系统开发】Ubuntu配置SFTP服务</a>)</p> +<p>当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。</p> +<p>我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111834424.png" +loading="lazy" +alt="image-20230411183456029" +></p> +<h4 id="3镜像烧录">3.镜像烧录 +</h4><ul> +<li> +<p>首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。</p> +</li> +<li> +<p>打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。</p> +</li> +<li> +<p>点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:<code>Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv</code>)。</p> +</li> +<li> +<p>点击Browse按钮,然后选择工程源码下的烧录镜像路径</p> +</li> +<li> +<p>点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111935608.png" +loading="lazy" +alt="image-20230411193521444" +></p> +<h4 id="4启动系统">4.启动系统 +</h4><p>将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111940183.jpg" +loading="lazy" +alt="3" +></p>【Linux系统开发】Ubuntu配置SFTP服务https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover.jpg" alt="Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务" /><h2 id="sftp介绍">SFTP介绍 +</h2><p>SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)</p> +<h2 id="安装步骤">安装步骤 +</h2><h4 id="1目标">1.目标: +</h4><p>在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。</p> +<h4 id="2查看ubuntu系统信息">2.查看Ubuntu系统信息 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071010234.png" +loading="lazy" +alt="image-20230407101026858" +></p> +<h4 id="3检查是否已安装sftp">3.检查是否已安装SFTP +</h4><p>在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071011398.png" +loading="lazy" +alt="image-20230407101132327" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">client</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">client</span> +</span></span><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">server</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。</p> +<h4 id="4新建用户组sftp-users并新建用户sftp">4.新建用户组SFTP-users,并新建用户SFTP +</h4><p>为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">adduser</span> <span class="nf">sftp</span> <span class="p">(</span><span class="err">这部分会让你新建用户组信息,建议最好截图保存下</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5给sftp赋权并新建用户组ssh-users">5.给SFTP赋权并新建用户组SSH-users +</h4><p>将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">G</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="nb">false</span> <span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">a</span> <span class="o">-</span><span class="n">G</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">bbc2005</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6创建并设置sftp用户目录">6.创建并设置SFTP用户目录 +</h4><p>为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chown</span> <span class="nl">yifang</span><span class="p">:</span><span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chmod</span> <span class="mi">770</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="7修改ssh配置文件">7.修改SSH配置文件 +</h4><p>在sshd_config文件的最后添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssh</span><span class="o">/</span><span class="n">sshd_config</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">AllowGroups</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">Match</span> <span class="n">Group</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">ChrootDirectory</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">AllowTcpForwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"><span class="n">X11Forwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">ForceCommand</span> <span class="n">internal</span><span class="o">-</span><span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些内容的意思是:</p> +<ul> +<li>只允许ssh-users和SFTP-users通过SSH访问系统;</li> +<li>针对SFTP-users用户,增加一些额外的设置: +<ul> +<li>将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);</li> +<li>禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。</li> +<li>如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。</li> +</ul> +</li> +</ul> +<h4 id="8sftp客户端验证">8.SFTP客户端验证 +</h4><p>首先将虚拟机重启:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">reboot</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。</p> +<p>查看ubuntu网络ip地址</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ifconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071038531.png" +loading="lazy" +alt="image-20230407103802472" +>zhe</p> +<p>这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考<a class="link" href="https://blog.devyi.com/archives/418/" target="_blank" rel="noopener" +>RaiDrive—将网盘映射为磁盘</a>)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071044734.png" +loading="lazy" +alt="image-20230407104441660" +></p> +<p>此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071046125.png" +loading="lazy" +alt="image-20230407104643007" +></p>【资讯】汇总一些嵌入式相关的公司https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/<img src="https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/cover.jpg" alt="Featured image of post 【资讯】汇总一些嵌入式相关的公司" /><blockquote> +<p>来源:https://zhuanlan.zhihu.com/p/585079427</p> +</blockquote> +<h2 id="1芯片行业">1.芯片行业 +</h2><p>目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。</p> +<p>代表性公司:</p> +<p>(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等</p> +<p>(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等</p> +<h2 id="2人工智能相关行业">2.人工智能相关行业 +</h2><p>(1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。</p> +<p>(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等</p> +<h2 id="3消费电子行业">3.消费电子行业 +</h2><p>消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等</p> +<h2 id="4传统汽车行业">4.传统汽车行业 +</h2><p>传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等</p> +<h2 id="5国企和军工">5.国企和军工 +</h2><p>国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。</p> +<h2 id="6传统电子电器类">6.传统电子电器类 +</h2><p>这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等</p> +<h2 id="7网络及通信设备">7.网络及通信设备 +</h2><p>主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等</p>【经验分享】ARM常用汇编指令https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/Wed, 29 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/cover.jpg" alt="Featured image of post 【经验分享】ARM常用汇编指令" /><h1 id="arm常用汇编指令">ARM常用汇编指令 +</h1><table> +<thead> +<tr> +<th>指令名称</th> +<th>作用</th> +</tr> +</thead> +<tbody> +<tr> +<td>EQU</td> +<td>给数字常量设置一个符号名,相当于C语言中的define</td> +</tr> +<tr> +<td>AREA</td> +<td>汇编一个新的代码段或者数据段</td> +</tr> +<tr> +<td>SPACE</td> +<td>分配内存空间</td> +</tr> +<tr> +<td>PRESERVE8</td> +<td>当前文件栈需要按照8字节对齐</td> +</tr> +<tr> +<td>EXPORT</td> +<td>声明一个符号具有全局属性,可被外部文件使用</td> +</tr> +<tr> +<td>DCD</td> +<td>以字为单位分配内存,要求4字节对齐,并要求初始化这些内存</td> +</tr> +<tr> +<td>PROC</td> +<td>定义子程序,与ENDP成对使用,表示子程序结束</td> +</tr> +<tr> +<td>WEAK</td> +<td>弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>IMPORT</td> +<td>声明标号来自外部文件,与C语言的EXETERN关键字类似</td> +</tr> +<tr> +<td>B</td> +<td>跳转到一个标号</td> +</tr> +<tr> +<td>ALIGN</td> +<td>编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>END</td> +<td>到达文件的末尾,文件结束</td> +</tr> +<tr> +<td>IF,ELSE,ENDIF</td> +<td>汇编条件分支语句,与C语言的if else类似</td> +</tr> +<tr> +<td>MRS</td> +<td>加载特殊功能寄存器的值到特殊功能寄存器</td> +</tr> +<tr> +<td>CBZ</td> +<td>比较,如果结果为0则转移</td> +</tr> +<tr> +<td>CBNZ</td> +<td>比较,如果结果非0则转移</td> +</tr> +<tr> +<td>LDR</td> +<td>从存储器中加载字到一个寄存器中</td> +</tr> +<tr> +<td>LDR[伪指令]</td> +<td>加载一个立即数或者一个地址到一个寄存器中。</td> +</tr> +<tr> +<td>LDRH</td> +<td>从存储器中加载半字到一个寄存器中</td> +</tr> +<tr> +<td>LDRB</td> +<td>从存储器中加载字节到一个寄存器中</td> +</tr> +<tr> +<td>STR</td> +<td>把一个寄存器按字节存储到存储器中</td> +</tr> +<tr> +<td>STRH</td> +<td>把一个寄存器的低半字存储到存储器中</td> +</tr> +<tr> +<td>STRB</td> +<td>把一个寄存器的低字节存储到存储器中</td> +</tr> +<tr> +<td>LDMIA</td> +<td>加载多个字,并且在加载后自增基址寄存器</td> +</tr> +<tr> +<td>STMIA</td> +<td>存储多个字,并且在存储后自增基址寄存器</td> +</tr> +<tr> +<td>ORR</td> +<td>按位或</td> +</tr> +<tr> +<td>BX</td> +<td>直接跳转到由寄存器给定的地址</td> +</tr> +<tr> +<td>BL</td> +<td>跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR</td> +</tr> +<tr> +<td>BLX</td> +<td>跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错</td> +</tr> +</tbody> +</table>【Git版本控制】Git命令详解https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/Fri, 17 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 【Git版本控制】Git命令详解" /><h2 id="前言">前言 +</h2><p>Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 <strong>回撤</strong>这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而<strong>版本管理工具能记录每次的修改</strong>,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。</p> +<p>下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。</p> +<h2 id="展示帮助信息">展示帮助信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git help -g +</span></span></code></pre></td></tr></table> +</div> +</div><p>The command output as below:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">The common Git guides are: +</span></span><span class="line"><span class="cl"> attributes Defining attributes per path +</span></span><span class="line"><span class="cl"> cli Git command-line interface and conventions +</span></span><span class="line"><span class="cl"> core-tutorial A Git core tutorial for developers +</span></span><span class="line"><span class="cl"> cvs-migration Git for CVS users +</span></span><span class="line"><span class="cl"> diffcore Tweaking diff output +</span></span><span class="line"><span class="cl"> everyday A useful minimum set of commands for Everyday Git +</span></span><span class="line"><span class="cl"> glossary A Git Glossary +</span></span><span class="line"><span class="cl"> hooks Hooks used by Git +</span></span><span class="line"><span class="cl"> ignore Specifies intentionally untracked files to ignore +</span></span><span class="line"><span class="cl"> modules Defining submodule properties +</span></span><span class="line"><span class="cl"> namespaces Git namespaces +</span></span><span class="line"><span class="cl"> repository-layout Git Repository Layout +</span></span><span class="line"><span class="cl"> revisions Specifying revisions and ranges for Git +</span></span><span class="line"><span class="cl"> tutorial A tutorial introduction to Git +</span></span><span class="line"><span class="cl"> tutorial-2 A tutorial introduction to Git: part two +</span></span><span class="line"><span class="cl"> workflows An overview of recommended workflows with Git +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">&#39;git help -a&#39; and &#39;git help -g&#39; list available subcommands and some concept guides. See &#39;git help &lt;command&gt;&#39; or &#39;git help &lt;concept&gt;&#39; to read about a specific subcommand or concept. +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到远程仓库的状态">回到远程仓库的状态 +</h2><p>抛弃本地所有的修改,回到远程仓库的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch --all &amp;&amp; git reset --hard origin/master +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重设第一个-commit">重设第一个 commit +</h2><p>也就是把所有的改动都重新放回工作区,并<strong>清空所有的 commit</strong>,这样就可以重新提交第一个 commit 了</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-ref -d HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看冲突文件列表">查看冲突文件列表 +</h2><p>展示工作区的冲突文件列表</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --name-only --diff-filter=U +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示工作区和暂存区的不同">展示工作区和暂存区的不同 +</h2><p>输出<strong>工作区</strong>和<strong>暂存区</strong>的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff +</span></span></code></pre></td></tr></table> +</div> +</div><p>还可以展示本地仓库中任意两个 commit 之间的文件变动:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff &lt;commit-id&gt; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区和最近版本的不同">展示暂存区和最近版本的不同 +</h2><p>输出<strong>暂存区</strong>和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --cached +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区工作区和最近版本的不同">展示暂存区、工作区和最近版本的不同 +</h2><p>输出<strong>工作区</strong>、<strong>暂存区</strong> 和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="快速切换到上一个分支">快速切换到上一个分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout - +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除已经合并到-master-的分支">删除已经合并到 master 的分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch --merged master | grep -v &#39;^\*\| master&#39; | xargs -n 1 git branch -d +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示本地分支关联远程仓库的情况">展示本地分支关联远程仓库的情况 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -vv +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="关联远程分支">关联远程分支 +</h2><p>关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -u origin/mybranch +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者在 push 时加上 -u 参数</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin/mybranch -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程分支">列出所有远程分支 +</h2><p>-r 参数相当于:remote</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -r +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出本地和远程分支">列出本地和远程分支 +</h2><p>-a 参数相当于:all</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -a +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看远程分支和本地分支的对应关系">查看远程分支和本地分支的对应关系 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote show origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="远程删除了分支本地也想删除">远程删除了分支本地也想删除 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote prune origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="创建并切换到本地分支">创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程分支中创建并切换到本地分支">从远程分支中创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; origin/&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地分支">删除本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -d &lt;local-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程分支">删除远程分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete &lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin :&lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重命名本地分支">重命名本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -m &lt;new-branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签">查看标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag +</span></span></code></pre></td></tr></table> +</div> +</div><p>展示当前分支的最近的 tag</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git describe --tags --abbrev=0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签详细信息">查看标签详细信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -ln +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="本地创建标签">本地创建标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag &lt;version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ git tag -a &lt;version-number&gt; -m &#34;v1.0 发布(描述)&#34; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="推送标签到远程仓库">推送标签到远程仓库 +</h2><p>首先要保证本地创建好了标签才可以推送标签到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin &lt;local-version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>一次性推送所有标签,同步到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --tags +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地标签">删除本地标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -d &lt;tag-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程标签">删除远程标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete tag &lt;tagname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="切回到某个标签">切回到某个标签 +</h2><p>一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b branch_name tag_name +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="放弃工作区的修改">放弃工作区的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>放弃所有修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout . +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="恢复删除的文件">恢复删除的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rev-list -n 1 HEAD -- &lt;file_path&gt; #得到 deleting_commit +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git checkout &lt;deleting_commit&gt;^ -- &lt;file_path&gt; #回到删除文件 deleting_commit 之前的状态 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以新增一个-commit-的方式还原某一个-commit-的修改">以新增一个 commit 的方式还原某一个 commit 的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git revert &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-commit-的状态并删除后面的-commit">回到某个 commit 的状态,并删除后面的 commit +</h2><p>和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;commit-id&gt; #默认就是-mixed参数。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --hard &lt;commit-id&gt; #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改上一个-commit-的描述">修改上一个 commit 的描述 +</h2><p>如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看-commit-历史">查看 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看某段代码是谁写的">查看某段代码是谁写的 +</h2><p>blame 的意思为‘责怪’,你懂的。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git blame &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="显示本地更新过-head-的-git-命令记录">显示本地更新过 HEAD 的 git 命令记录 +</h2><p>每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reflog +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改作者名">修改作者名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend --author=&#39;Author Name &lt;email@address.com&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改远程仓库的-url">修改远程仓库的 url +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote set-url origin &lt;URL&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="增加远程仓库">增加远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote add origin &lt;remote-url&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程仓库">列出所有远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看两个星期内的改动">查看两个星期内的改动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git whatchanged --since=&#39;2 weeks ago&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把-a-分支的某一个-commit放到-b-分支上">把 A 分支的某一个 commit,放到 B 分支上 +</h2><p>这个过程需要 cherry-pick 命令,<a class="link" href="http://sg552.iteye.com/blog/1300713#bc2367928" target="_blank" rel="noopener" +>参考</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;branch-name&gt; &amp;&amp; git cherry-pick &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="给-git-命令起别名">给 git 命令起别名 +</h2><p>简化命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global alias.&lt;handle&gt; &lt;command&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">比如:git status 改成 git st,这样可以简化命令 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git config --global alias.st status +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="存储当前的修改但不用提交-commit">存储当前的修改,但不用提交 commit +</h2><p>详解可以参考<a class="link" href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137602359178794d966923e5c4134bc8bf98dfb03aea3000" target="_blank" rel="noopener" +>廖雪峰老师的 git 教程</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="保存当前状态包括-untracked-的文件">保存当前状态,包括 untracked 的文件 +</h2><p>untracked 文件:新建的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-stashes">展示所有 stashes +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash list +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-stash-的状态">回到某个 stash 的状态 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash apply &lt;stash@{n}&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到最后一个-stash-的状态并删除这个-stash">回到最后一个 stash 的状态,并删除这个 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash pop +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除所有的-stash">删除所有的 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash clear +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从-stash-中拿出某个文件的修改">从 stash 中拿出某个文件的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;stash@{n}&gt; -- &lt;file-path&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-tracked-的文件">展示所有 tracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files -t +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-untracked-的文件">展示所有 untracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有忽略的文件">展示所有忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others -i --exclude-standard +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的文件">强制删除 untracked 的文件 +</h2><p>可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,<strong>注意两点</strong>:</p> +<ol> +<li>clean 后,删除的文件无法找回</li> +<li>不会影响 tracked 的文件的改动,只会删除 untracked 的文件</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;file-name&gt; -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的目录">强制删除 untracked 的目录 +</h2><p>可以用来删除新建的目录,<strong>注意</strong>:这个命令也可以用来删除 untracked 的文件。详情见上一条</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;directory-name&gt; -df +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示简化的-commit-历史">展示简化的 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --pretty=oneline --graph --decorate --all +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把某一个分支导出成一个文件">把某一个分支导出成一个文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git bundle create &lt;file&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从包中导入分支">从包中导入分支 +</h2><p>新建一个分支,分支内容就是上面 git bundle create 命令导出的内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone repo.bundle &lt;repo-dir&gt; -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="执行-rebase-之前自动-stash">执行 rebase 之前自动 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rebase --autostash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程仓库根据-id拉下某一状态到本地分支">从远程仓库根据 ID,拉下某一状态,到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch origin pull/&lt;id&gt;/head:&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="详细展示一行中的修改">详细展示一行中的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --word-diff +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="清除-gitignore-文件中记录的文件">清除 gitignore 文件中记录的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean -X -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-alias-和-configs">展示所有 alias 和 configs +</h2><p><strong>注意:</strong> config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --local --list (当前目录) +</span></span><span class="line"><span class="cl">git config --global --list (全局) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示忽略的文件">展示忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git status --ignored +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="commit-历史中显示-branch1-有的但是-branch2-没有-commit">commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log Branch1 ^Branch2 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中显示-gpg-签名">在 commit log 中显示 GPG 签名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --show-signature +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除全局设置">删除全局设置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global --unset &lt;entry-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="新建并切换到新分支上同时这个分支没有任何-commit">新建并切换到新分支上,同时这个分支没有任何 commit +</h2><p>相当于保存修改,但是重写 commit 历史</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout --orphan &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示任意分支某一文件的内容">展示任意分支某一文件的内容 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git show &lt;branch-name&gt;:&lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-下来指定的单一分支">clone 下来指定的单一分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone -b &lt;branch-name&gt; --single-branch https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-最新一次提交">clone 最新一次提交 +</h2><p>只会 clone 最近一次提交,将减少 clone 时间</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --depth=1 https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略某个文件的改动">忽略某个文件的改动 +</h2><p>关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><p>恢复 track 指定文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --no-assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略文件的权限变化">忽略文件的权限变化 +</h2><p>不再将文件的权限变化视作改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config core.fileMode false +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以最后提交的顺序列出所有-git-分支">以最后提交的顺序列出所有 Git 分支 +</h2><p>最新的放在最上面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git for-each-ref --sort=-committerdate --format=&#39;%(refname:short)&#39; refs/heads/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中查找相关内容">在 commit log 中查找相关内容 +</h2><p>通过 grep 查找,given-text:所需要查找的字段</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --all --grep=&#39;&lt;given-text&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把暂存区的指定-file-放到工作区中">把暂存区的指定 file 放到工作区中 +</h2><p>不添加参数,默认是 -mixed</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制推送">强制推送 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push -f &lt;remote-name&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p>瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/Mon, 22 Aug 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/<img src="https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/cover.jpg" alt="Featured image of post 瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包" /><h4 id="一创建工程选择segger_rtt软件包">一、创建工程,选择SEGGER_RTT软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/015bb29dd26648570d03e65cd419f972.png" +loading="lazy" +alt="image-20221003133030692" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fb34abd8ec95bf35f09fb3bcde1f5d1d.png" +loading="lazy" +alt="image-20221003133219108" +></p> +<h4 id="2添加jlinkrtt初始化函数-路径rt-threadsrckservicec-">2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ] +</h4><p>在<code>rt_console_set_device</code>前调用<code>rt_hw_jlink_rtt_init</code>初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/492ff3b5ab1bf24e62a4380f3d47bf29.png" +loading="lazy" +alt="image-20221003133721333" +></p> +<h4 id="3控制台对接上jlinkrtt">3、控制台对接上jlinkRtt +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rtconfg.h +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// 修改RT_CONSOLE_DEVICE_NAME为空 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/img_convert/a4101391c61fad4add9376b4ebcd71e9.png" +loading="lazy" +alt="image-20221003134935152" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">shell</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="nl">D</span><span class="p">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">components</span><span class="err">\</span><span class="n">finsh</span><span class="err">\</span><span class="n">shell</span><span class="p">.</span><span class="n">c</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 1、首先添加以下头文件 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT_Conf.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 2、修改finsh_getchar */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">finsh_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_DEVICE +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">char</span> <span class="n">ch</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_POSIX_STDIO +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span><span class="p">(</span><span class="nf">read</span><span class="p">(</span><span class="n">STDIN_FILENO</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="cm">/* EOF */</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">rt_device_t</span> <span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_ASSERT</span><span class="p">(</span><span class="n">shell</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="nf">rt_device_read</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">rx_sem</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span> <span class="o">!=</span> <span class="n">device</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_POSIX_STDIO */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_DEVICE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">src</span><span class="err">\</span><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">RT_WEAK</span> <span class="kt">void</span> <span class="nf">rt_hw_console_output</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* empty console output */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">str</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="sc">&#39;\n&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SEGGER_RTT_printf</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s">&#34;%s&#34;</span><span class="p">,</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">RTM_EXPORT</span><span class="p">(</span><span class="n">rt_hw_console_output</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4实验效果">4、实验效果 +</h4><p>首先确保已经下载好<code>J-Link RTT Viewer</code>,直接去<a class="link" href="https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/" target="_blank" rel="noopener" +>官网</a>下载最新版本即可</p> +<p>然后编译和下载工程,注意下载方式为<code>J-Link</code></p> +<p>双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看<code>_SEGGER_RTT</code>变量地址(全局搜索即可,找到.bss._SEGGER_RTT)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/608cb3d791c683d7886a92eef5ae848f.png" +loading="lazy" +alt="image-20221003140449806" +></p> +<p>打开<code>J-Link RTT Viewer</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5e3d4a57e4a6b55dd62f61b5d6577105.png" +loading="lazy" +alt="image-20221003140736161" +></p> +<p>此时就可以正常使用segger_rtt了!</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/d09d8a0f28e2c45542199eb982dfed6e.png" +loading="lazy" +alt="image-20221003140911791" +></p>【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Fri, 29 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/cover.jpg" alt="Featured image of post 【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制" /><h4 id="一了解tortoisegit">一、了解TortoiseGit +</h4><p>TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。</p> +<p>由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。</p> +<p>TortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。</p> +<p>它是在<a class="link" href="https://www.gnu.org/licenses/gpl-2.0" target="_blank" rel="noopener" +>GPL</a>下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。</p> +<h4 id="二安装giit及tortoisegit">二、安装GIit及TortoiseGit +</h4><ul> +<li>Git下载官网: <a class="link" href="https://gitforwindows.org/index.html" target="_blank" rel="noopener" +>https://gitforwindows.org/index.html</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4a21fd0a6bd1453ba31032ce73c67d73.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>TortoiseGit下载官网:<a class="link" href="https://tortoisegit.org/download/" target="_blank" rel="noopener" +>https://tortoisegit.org/download/</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ba9793defe4baa02684e53320b79bde4.png" +loading="lazy" +alt="image-20220720090147944" +></p> +<ul> +<li>同时下载语言包</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b9cb668ce4c7a1ba2cda1a6bab5a0a76.png" +loading="lazy" +></p> +<p>当然这里也有百度网盘链接,也可点击下方链接进行下载</p> +<p>链接:<a class="link" href="https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs</a> +提取码:dzbs</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/db691a46832cc291932ff63fcc3e9a74.png" +loading="lazy" +alt="image-20220720090721507" +></p> +<h4 id="三tortoisegit配置">三、TortoiseGit配置 +</h4><p>完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67fb3421c49f0c5e90e76fa3c04c9b71.png" +loading="lazy" +alt="image-20220720091049882" +></p> +<p>这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/853a58d535b9e2370949ccb7917b80b5.png" +loading="lazy" +alt="image-20220720091218159" +></p> +<p>配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/e70b76490f6f5cfc699d79df3968e1fe.png" +loading="lazy" +alt="image-20220720091439829" +></p> +<p>点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[credential] +</span></span><span class="line"><span class="cl"> helper = store +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成后保存,关闭记事本,确定即可。</p> +<p>  则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。</p> +<p>  如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。</p> +<h4 id="四添加github-ssh-keys及密钥上传">四、添加GitHub SSH Keys及密钥上传 +</h4><p>首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\TortoiseGit\bin\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/33d7c521e31040d4921e11ab1b12bd74.png" +loading="lazy" +alt="image-20220720092721281" +> +<img src="https://img-blog.csdnimg.cn/img_convert/3f27c4682dc82b0bd0f3ef5c89a1df7e.png" +loading="lazy" +alt="image-20220720093308539" +></p> +<p>然后复制下方公钥,</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2a5f6daf15cc2e9935764b207b726cf7.png" +loading="lazy" +alt="image-20220720093236525" +></p> +<p>打开github,完成下图操作:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/52cf49261a89b3186083dfb7240ea8dd.png" +loading="lazy" +alt="image-20220815182247315" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/1db55857a0118c8cabc02f9a5c4bb19b.png" +loading="lazy" +alt="image-20220815182404425" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b406ac32656957356de898117c6bb17f.png" +loading="lazy" +alt="image-20220815182541297" +></p> +<h4 id="五使用tortoisegit提交代码到远端仓库">五、使用TortoiseGit提交代码到远端仓库 +</h4><p>在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/846315f99c2e767666f7be83437e4969.png" +loading="lazy" +alt="image-20220815185026555" +></p> +<p>鼠标右键可以看到选项<code>Git在这里创建版本库</code>,点击创建版本库</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bcb80e2391a690906240fd0d1b197e7a.png" +loading="lazy" +alt="image-20220815185825412" +></p> +<p>鼠标右键打开TortoiseGit-&gt;设置(Settings)-&gt;Git-&gt;远端(Remote),进行如下配置</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a1f9b059fb25b079395ad2588d51c0c5.png" +loading="lazy" +alt="image-20220815191405483" +></p> +<p>此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9c4fbf6ee5360e497644e6330255a278.png" +loading="lazy" +alt="image-20220815190637369" +></p> +<p>我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">正常的:绿色的对号 +</span></span><span class="line"><span class="cl">被修改过的:红色感叹号 +</span></span><span class="line"><span class="cl">新添加的:蓝色的加号 +</span></span><span class="line"><span class="cl">未受控的(无版本控制的):蓝色的问号 +</span></span><span class="line"><span class="cl">忽略不受控的:灰色的减号 +</span></span><span class="line"><span class="cl">删除的:红色的x号 +</span></span><span class="line"><span class="cl">有冲突的:黄色的感叹号 +</span></span></code></pre></td></tr></table> +</div> +</div><p>鼠标右键添加文件</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f146752e79d7bd6a4e9287e2c32ad3c1.png" +loading="lazy" +alt="image-20220815191829438" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/50b75011172011ae724d81bd921f8fdc.png" +loading="lazy" +alt="image-20220815191933736" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a9acdcdf6d14730de5e91df7564f65f8.png" +loading="lazy" +alt="image-20220815192002035" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/6439911282c3c25bde45fa033f3a58b3.png" +loading="lazy" +alt="image-20220815192321480" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/73d32ab54fc9914ea2d1a967c5b91065.png" +loading="lazy" +alt="image-20220815193032859" +></p> +<p><strong><code>注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次</code></strong></p> +<p>总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)</p> +<p><em><strong><code>添加-&gt;提交-&gt;拉取-&gt;推送</code></strong></em></p> +<p>那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!</p>x210开发板根目录文件系统构建https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/Thu, 28 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/cover.jpg" alt="Featured image of post x210开发板根目录文件系统构建" /><h2 id="一开发板配置">一、开发板配置 +</h2><p>(使用secureCRT) +首先确保开发板完成以下配置:</p> +<p>主机IP: +<code>set ipaddr192.168.1.10</code> +服务器IP: +<code>set serverip 192.168.1.141</code> +网关: +<code>set gatewayip 192.168.1.1</code> +子网掩码: +<code>set netmask 255.255.255.0</code> +内核驱动设置: +<code>set bootcmd 'tftp 30008000 zImage; bootm 30008000'</code> +bootargs配置: +<code>set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200</code></p> +<p>最后输入save保存一下,这样开发板的网络和内核配置就设置好了</p> +<h2 id="二了解rootfs">二、了解rootfs +</h2><p>rootfs的两种表现形式: +1、nfs方式启动的文件夹形式的rootfs(主机)</p> +<p>2、用来烧录的镜像形式rootfs(开发板)</p> +<h2 id="三虚拟机文件配置">三、虚拟机文件配置 +</h2><h4 id="1目录配置">1.目录配置 +</h4><p>首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: +<code>rootfs x210_bsp</code></p> +<p>这时候我们需要知道这两个文件夹下有什么:</p> +<blockquote> +<ul> +<li>x210_bsp:用于uboot烧录和配置</li> +<li>rootfs:用于挂载开发板根文件系统</li> +</ul> +</blockquote> +<h4 id="2x210_bsp配置">2.x210_bsp配置 +</h4><p>首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压</p> +<p><img src="https://img-blog.csdnimg.cn/b4f56856fa1447b6b49ea43313bc141a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用</p> +<h4 id="3rootfs配置">3.rootfs配置 +</h4><p>首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压</p> +<p><img src="https://img-blog.csdnimg.cn/87600bf5cbf44ac3a94db3bc7bd01d78.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件</p> +<h4 id="4make-menuconfig">4.make menuconfig +</h4><p>进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单</p> +<blockquote> +<p>这里我们按下面操作完成网络配置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[*]Networking support ---&gt; +</span></span><span class="line"><span class="cl"> Networking options ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/a33a8e4e25bc4335b263cdbc59bd79a6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>网络文件系统设置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">File systems ---&gt; +</span></span><span class="line"><span class="cl"> [*]Networking File Systems ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>有需要把开发板作为服务器端的也可以选择把<code>NFS server support</code>设置打开,这里我们仅实验客户端</p> +<p><img src="https://img-blog.csdnimg.cn/ce11d76876fd463db53915dffde15776.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上配置结束后输入命令<code>make</code>编译,至此开发板uboot的网络和文件系统部分配置结束。</p> +<h2 id="四busybox的移植实战">四、busybox的移植实战 +</h2><h4 id="1了解busybox">1、了解busybox +</h4><blockquote> +<p>busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。</p> +</blockquote> +<h4 id="2busybox源码获取">2、busybox源码获取 +</h4><p><a class="link" href="http://www.busybox.net/" target="_blank" rel="noopener" +>busybox官网</a></p> +<p><code>注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)</code></p> +<h4 id="3busybox配置">3、busybox配置 +</h4><p>(1)修改Makefile</p> +<p>首先进入<code>~/rootfs/x210_rootfs/busybox-1.24.1</code>目录下</p> +<p>输入命令<code>vi Makefile</code>进入脚本进行以下修改</p> +<p>173行:<code>CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-</code> +<code>注意:此处的交叉编译链需要对照自己电脑的交叉编译链</code> +191行:<code>ARCH=arm</code></p> +<p><img src="https://img-blog.csdnimg.cn/988e15e86dde4807aa26011e6686bc6f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>(2)make menuconfig配置</p> +<p>Tip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 +因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。</p> +<p>make menuconfig</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Settings</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="n">Build</span> <span class="n">Options</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Build</span> <span class="n">BusyBox</span> <span class="n">as</span> <span class="n">a</span> <span class="k">static</span> <span class="n">binary</span><span class="p">(</span><span class="n">no</span> <span class="n">shared</span> <span class="n">libs</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Library</span> <span class="n">Tuning</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">vi</span><span class="o">-</span><span class="n">style</span> <span class="n">line</span> <span class="n">editing</span> <span class="n">commands</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Fancy</span> <span class="n">shell</span> <span class="n">prompts</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">Module</span> <span class="n">Utilities</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span> <span class="p">]</span><span class="n">Simplified</span> <span class="n">modutils</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">insmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">rmmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">lsmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">modprobe</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">depmod</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">System</span> <span class="n">Utilities</span><span class="o">---&gt;</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">mdev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">mdev</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">subdirs</span><span class="o">/</span><span class="n">symlinks</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">regular</span> <span class="n">expressions</span> <span class="n">substitutions</span> <span class="n">when</span> <span class="n">renaming</span> <span class="n">dev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">command</span> <span class="n">execution</span> <span class="n">at</span> <span class="n">device</span> <span class="n">addition</span><span class="o">/</span><span class="n">removal</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">loading</span> <span class="n">of</span> <span class="n">firmwares</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>大家学习使用的时候跟着上面的进行配置即可 +配置完成后,输入以下命令: +<code>make -j4</code> (4代表我主机的内核数) +无报错继续下一步: +make install</p> +<blockquote> +<p>解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装</p> +</blockquote> +<p>(3)设置busybox安装路径</p> +<ul> +<li><code>make menuconfig</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Busybox Settings ---&gt; +</span></span><span class="line"><span class="cl"> Installation Options (&#34;make install&#34; behavior) ---&gt; +</span></span><span class="line"><span class="cl"> (./)BusyBox installation prefix) //这里设置安装路径 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cf7de167425b47acaff070d610f78d1f.png" +loading="lazy" +></p> +<p>(4)解决方案 +在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。</p> +<p>make -j4编译可能遇到的问题:</p> +<ul> +<li><code>sync.c(text.sync_main+0x78):undefined reference to 'syncfs'</code></li> +</ul> +<p><code>分析:</code>可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。</p> +<p><code>解决方法:</code></p> +<p><code>make menuconfig</code> +点击/进入搜索,输入SYNC,根据提示禁用SYNC +最后再make -j4编译一下即可</p> +<p><img src="https://img-blog.csdnimg.cn/7defb1eda80748d29c73a564f2e631be.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2b4ded5286854f1ca4e7d8fae5e148c4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<img src="https://img-blog.csdnimg.cn/932a1580f3b54a5ca685be2b7c5c1dd7.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。</p> +<p>(5)make install简述</p> +<ul> +<li>默认安装位置:./_install</li> +<li>文件包含有:bin linuxrc sbin usr</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/002a97e1448542f784b04d188f6cb7f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->ls -l可以看到: linuxrc -&gt; bin/busybox //这个linuxrc其实就是个符号链接 <!-- raw HTML omitted --></p> +<p><img src="https://img-blog.csdnimg.cn/b97a1a96e2a94503832d05c0f8ca072e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->这里也不难发现,bin下的所有的符号链接都指向了busybox<!-- raw HTML omitted --></p> +<p>(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">make menuconfig +</span></span><span class="line"><span class="cl"> Busybox Settings —&gt; +</span></span><span class="line"><span class="cl"> Installation Options (“make install” behavior) —&gt; +</span></span><span class="line"><span class="cl"> (/root/rootfs/x210_rootfs)BusyBox installation prefix +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行<code>make install</code>后,回到被挂载的目录下,可以发现这四个文件已经生成。</p> +<h2 id="五nfs挂载根文件系统">五、NFS挂载根文件系统 +</h2><h4 id="1nfs简述">1.NFS简述 +</h4><ul> +<li>NFS 是Network File System的缩写,即网络文件系统。</li> +<li>功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。</li> +</ul> +<h4 id="2nfs服务器安装">2.NFS服务器安装 +</h4><p><code>sudo apt-get install nfs-kernel-server</code></p> +<h4 id="3nfs使用过程">3.NFS使用过程 +</h4><p>启动NFS服务器-&gt;启动NFS客户端-&gt;挂载NFS目录</p> +<h4 id="4nfs配置">4.NFS配置 +</h4><ul> +<li>输入命令<code>vim /etc/exports</code></li> +</ul> +<p>在最后一行修改</p> +<ul> +<li><code>&quot;文件挂载目录&quot; *(rw,sync,no_root_squash,no_subtree_check)</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a355d9b6e233404ea19531fa04947910.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>保存退出后,输入<code>mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs</code>(根据实际情况修改)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/9383c4e9c6e74c7485d07a6aec6f99fd.png" +loading="lazy" +></p> +<ul> +<li>输入命令<code>/etc/init.d/nfs-kernel-server restart</code>重启NFS服务</li> +</ul> +<h2 id="六开发板根目录配置">六、开发板根目录配置 +</h2><p>首先将etc目录放置到挂载根目录下</p> +<p>etc目录下载:</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>点击此处</a></p> +<h4 id="1inittab文件详解">1.inittab文件详解 +</h4><p>&lt;1&gt;添加一个典型的inittab文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>inittab下载</a></p> +<p>&lt;2&gt;inittab格式解析</p> +<p><code>id:runlevels:action:process</code></p> +<p><img src="https://img-blog.csdnimg.cn/4f374d2fe1ca4f7da6f22403e314525f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>解释:</p> +<ul> +<li>id:标识符,即代表记录的名字</li> +<li>runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/dd8867359c0c44c6945fc29dbf0a90a3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>action:用于描述该级别该执行什么操作(部分说明)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/99fb967e453c456b989bd57ec0e84020.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>process:具体执行的命令</li> +</ul> +<p>&lt;3&gt;了解busybox init与inittab之间的关系</p> +<ul> +<li>busybox init进程主要完成系统的初始化工作。</li> +</ul> +<p>busybox init进程的工作流程:</p> +<blockquote> +<p><!-- raw HTML omitted -->为init设置信号处理过程-&gt;初始化控制台-&gt;剖析/etc/inittab文件-&gt;执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS-&gt;执行所有导致 init 暂停的 inittab 命令(动作类型: wait)-&gt;执行所有仅执行一次的 inittab(动作类型: once)<!-- raw HTML omitted --></p> +</blockquote> +<ul> +<li>一旦完成以上工作, init 进程便会<code>循环执行</code>以下进程:</li> +</ul> +<blockquote> +<p>&lt;1&gt;执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) +&lt;2&gt;执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)</p> +</blockquote> +<ul> +<li>简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。</li> +</ul> +<p>注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。</p> +<p>&lt;4&gt;配置 +vi命令打开inittab模板文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#first:run the system script file 注释 +</span></span><span class="line"><span class="cl">::sysinit:/etc/init.d/rcS //在控制台初始化之前执行rcS +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::askfirst:-/bin/sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::ctrlaltdel:-/sbin/reboot //执行控制台时的打印信息 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#umount all filesystem //同时按住3键可以重启 +</span></span><span class="line"><span class="cl">::shutdown:/bin/umount -a -r//关机时接触挂载init +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#restart init process//重启时启动 +</span></span><span class="line"><span class="cl">::restart:/sbin/init +</span></span></code></pre></td></tr></table> +</div> +</div><p>修改脚本: +<img src="https://img-blog.csdnimg.cn/0ccb3db4d10c417b9eeb5526f87c7793.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rcs文件详解">2.rcS文件详解 +</h4><p>&lt;1&gt;添加一个典型的rcS文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>rcS下载</a></p> +<p>&lt;2&gt;rcS文件解析</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/sh 需要继续添加环境变量,在后面:/new 即可 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">PATH</span><span class="o">=</span>/sbin:/bin:/usr/sbin:/usr/bin +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">runlevel</span><span class="o">=</span>S +</span></span><span class="line"><span class="cl"><span class="nv">prevlevel</span><span class="o">=</span>N +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">umask</span> <span class="m">022</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> PATH runlevel prevlevel +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -a +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>PATH=xxx</li> +</ul> +<blockquote> +<p>PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。</p> +</blockquote> +<ul> +<li>runlevel=</li> +</ul> +<blockquote> +<p>linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/2c17661c32464ad8a0c96c654e622289.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>umask=</li> +</ul> +<blockquote> +<p>umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。</p> +</blockquote> +<ul> +<li>mount -a</li> +</ul> +<blockquote> +<p>mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)</p> +</blockquote> +<h4 id="3rcs实战">3.rcS实战 +</h4><p>首先将前面提供的etc压缩包模板下载至共享文件夹</p> +<p>&lt;1&gt;输入命令打开rcS脚本:<code>vi etc/init.d/rcS</code>。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了</p> +<p>&lt;2&gt;mdev</p> +<blockquote> +<p>udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。</p> +</blockquote> +<p>rcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在<code>rcS</code>文件中添加以下与mdev有关的2行配置项后:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echo /sbin/mdev &gt; /proc/sys/kernel/hotplug +</span></span><span class="line"><span class="cl">mdev -s +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/d84ea4a6677a4af08741ba6c4b6db580.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>再次启动系统后发现/dev目录下生成了很多的设备驱动文件</p> +<p>&lt;3&gt;hostname</p> +<p><code>我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名</code></p> +<p>hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。</p> +<ul> +<li>添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname</li> +</ul> +<p>&lt;4&gt;ifconfig</p> +<p>(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40</p> +<p><img src="https://img-blog.csdnimg.cn/5842d7cc0dd94c3fbd348189e908f09b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>&lt;5&gt;mount挂载测试</p> +<p>这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="k">var</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">tmp</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="o">......</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,<code>输入mkdir命令在根目录依次创建即可</code>。</p> +<h2 id="七动态链接库的拷贝">七、动态链接库的拷贝 +</h2><h4 id="1静态编译链接测试">1.静态编译链接测试 +</h4><p>首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a.c file-&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">int main() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> printf(&#34;hello world!\n&#34;); +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2解决办法">2.解决办法: +</h4><p><code>拷贝一份动态链接库文件到开发板根目录下</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3解释">3.解释: +</h4><p><img src="https://img-blog.csdnimg.cn/6e39e3914f954ff7967b904a8aa576c5.png" +loading="lazy" +></p> +<p>这时候执行命令./a.out发现可以正常打印</p> +<h4 id="4strip工具">4.strip工具 +</h4><p>动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在<code>传统的嵌入式系统中flash空间是有限的</code>,为了<code>节省空间</code>常常把这些符号信息去掉。这样节省空间并且不影响运行。</p> +<p>去掉符号信息的命令:</p> +<p><code>arm-linux-strip *so*</code></p> +<h2 id="八ext2格式镜像烧录">八、ext2格式镜像烧录 +</h2><h4 id="1确定文件夹格式的rootfs可用">1. 确定文件夹格式的rootfs可用 +</h4><p>前面我们已经提前配置好,此处不再赘述</p> +<p><img src="https://img-blog.csdnimg.cn/560f47331e76495994c412e7f9e97425.png" +loading="lazy" +></p> +<h4 id="2ext2镜像制作">2.ext2镜像制作 +</h4><ul> +<li> +<p>首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。</p> +</li> +<li> +<p>然后输入以下命令:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">losetup /dev/loop1 rootfs.ext2 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mke2fs -m 0 /dev/loop1 10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -t ext2 /dev/loop1 ./ext2_rootfs/ +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时我们复制一份开发板根目录到ext2_rootfs下</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp rootfs.ext2 /mnt/hgfs/Myshare/ -f +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>进入~/rootfs目录,执行清除卸载命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">umount /dev/loop1 +</span></span><span class="line"><span class="cl">losetup -d /dev/loop1 +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时在rootfs目录下可以看见生成了一个rootfs.ext2镜像文件,我们将其复制到共享文件夹下,然后再将其复制到电脑<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>fastboot</a>目录下,执行uboot烧录操作,借鉴该博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a></li> +</ul> +<p>至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!</p> +<hr> +<p>参考资料:</p> +<ul> +<li> +<p><a class="link" href="https://blog.csdn.net/wangweijundeqq/article/details/82533485?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>Linux开发之根文件系统构建及过程详解</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010299133/article/details/93414146" target="_blank" rel="noopener" +>busybox init进程和/etc/inittab关系</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010311609/article/details/123137181?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165080397516782184664736%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165080397516782184664736&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-123137181.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=NFS%E6%8C%82%E8%BD%BDlinux&#43;&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>NFS-LINUX挂载实践</a></p> +</li> +</ul>Ubuntu命令查看手册https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/Mon, 25 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/cover.jpg" alt="Featured image of post Ubuntu命令查看手册" /><h2 id="进程管理类">进程管理类 +</h2><p>1.top命令</p> +<blockquote> +<ul> +<li>top命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。</li> +<li>top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。</li> +</ul> +</blockquote> +<p>2.htop命令</p> +<blockquote> +<ul> +<li>htop命令是top的改进版。</li> +<li>默认情况下,大多数Linux发行版本都没有安装htop。</li> +<li>htop命令显示的信息与top相同,但它的界面更人性化。</li> +</ul> +</blockquote> +<p>3.pstree</p> +<blockquote> +<ul> +<li>pstree命令也可以显示进程信息。</li> +<li>它以树的形式显示进程。</li> +</ul> +</blockquote> +<p>4.kill</p> +<blockquote> +<ul> +<li>kill命令可以根据进程ID来杀死进程。</li> +<li>你可以使用ps -A,top,或者grep命令获取到进程ID。</li> +</ul> +</blockquote> +<pre><code>从技术层面来讲,kill命令可以发送任何信号给一个进程。 +你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。 +</code></pre> +<hr> +<h2 id="文件操作类基础篇">文件操作类(基础篇) +</h2><blockquote> +<p><strong>新建文件:touch</strong><br> +详细文档通过 man [command] 查看</p> +</blockquote> +<blockquote> +<p><strong>管理文件</strong></p> +</blockquote> +<ul> +<li>rm: 删除文件或目录(-r)</li> +<li>mkdir 新建目录</li> +<li>cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r)</li> +<li>mv 移动或重命名文件、目录</li> +</ul> +<blockquote> +<p><strong>压缩tzip文件</strong></p> +</blockquote> +<ul> +<li>zip FileName.zip DirName # 将DirName本身压缩</li> +<li>zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩</li> +</ul> +<blockquote> +<p><strong>解压zip文件</strong></p> +</blockquote> +<ul> +<li>unzip filename</li> +</ul> +<blockquote> +<p><strong>查找含<code>spark</code>的目录、文件</strong></p> +</blockquote> +<ul> +<li>find /home/jack -name &lsquo;<em>spark</em>&rsquo;</li> +</ul> +<blockquote> +<p><strong>更改密码</strong></p> +</blockquote> +<ul> +<li>passwd</li> +</ul> +<blockquote> +<p><strong>更改文件名或移动文件位置</strong></p> +</blockquote> +<ul> +<li>语句:mv oldFileName newFileName</li> +<li>示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt</li> +</ul> +<blockquote> +<p><strong>删除文件</strong></p> +</blockquote> +<ul> +<li>删除文件: rm test.txt</li> +<li>删除空文件夹: rmdir test</li> +<li>删除非空文件夹及其目录下的所有文件夹及文件:rm -r test</li> +<li>删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt)</li> +</ul> +<h2 id="防火墙状态">防火墙状态 +</h2><p>首先需要输入安装命令: +<code>apt install ufw</code></p> +<blockquote> +<p>查看防火墙当前状态 +<code>sudo ufw status</code></p> +</blockquote> +<blockquote> +<p>开启防火墙 +<code>sudo ufw enable</code></p> +</blockquote> +<blockquote> +<p>关闭防火墙 +<code>sudo ufw disable</code></p> +</blockquote> +<blockquote> +<p>查看防火墙版本 +<code>sudo ufw version</code></p> +</blockquote> +<blockquote> +<p>默认允许外部访问本机 +<code>sudo ufw default allow</code></p> +</blockquote> +<blockquote> +<p>默认拒绝外部访问主机 +<code>sudo ufw default deny</code></p> +</blockquote> +<blockquote> +<p>允许外部访问443端口 +<code>sudo ufw allow 443</code></p> +</blockquote> +<blockquote> +<p>拒绝外部访问443端口 +<code>sudo ufw deny 443</code></p> +</blockquote> +<blockquote> +<p>允许某个IP地址访问本机所有端口 +<code>sudo ufw allow from 192.168.0.1</code></p> +</blockquote> +<h2 id="网络设置">网络设置 +</h2><blockquote> +<p>重置网卡 +sudo /etc/init.d/networking restart</p> +</blockquote>CPK-RA6M4智慧门禁系统教学https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/cover.jpg" alt="Featured image of post CPK-RA6M4智慧门禁系统教学" /><p><img src="https://img-blog.csdnimg.cn/img_convert/b98bb037592975e68632b30a8e0845f6.png" +loading="lazy" +alt="image-20220804171524901" +></p> +<h2 id="1项目介绍">1、项目介绍 +</h2><p>本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。</p> +<p>下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。</p> +<h2 id="2前期准备">2、前期准备 +</h2><p>开发工具:</p> +<ul> +<li>RT-Thread Studio</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a95d6ef5c3224144b554bcb416691bcf.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。</p> +<p>RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。</p> +<p>下载链接:<a class="link" href="https://www.rt-thread.org/page/download.html#studio" target="_blank" rel="noopener" +>RT-Thread Studio 下载</a></p> +<ul> +<li>瑞萨FSP(灵活配置软件包)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fbdf24dd4b66b39b2f108f558ecf4617.png" +loading="lazy" +alt="Flexible Software Package (FSP)" +></p> +<p>瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。</p> +<p>下载链接:<a class="link" href="https://github.com/renesas/fsp/releases/tag/v3.5.0" target="_blank" rel="noopener" +>瑞萨FSP v3.5.0</a></p> +<p>模块:</p> +<ul> +<li>AHT10</li> +<li>ESP8266</li> +<li>RC522及读卡标签</li> +<li>ssd1306 OLED显示屏</li> +</ul> +<h2 id="3模块介绍及使用">3、模块介绍及使用 +</h2><h4 id="31-aht10">3.1 AHT10 +</h4><h6 id="311底层i2c通信协议简介">3.1.1底层I2C通信协议简介 +</h6><p>I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。</p> +<p>而I2C通信的读写数据是通过等待从机的应答信号(ACK)。</p> +<p>也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。</p> +<p>这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。</p> +<p>当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。</p> +<p>简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。</p> +<h6 id="312-sensor框架的使用">3.1.2 sensor框架的使用 +</h6><p>在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。</p> +<p>掌握sensor框架的使用,需要了解一下API的调用:</p> +<table> +<thead> +<tr> +<th style="text-align:center"><strong>函数</strong></th> +<th style="text-align:center"><strong>描述</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">rt_device_find()</td> +<td style="text-align:center">根据传感器设备设备名称查找设备获取设备句柄</td> +</tr> +<tr> +<td style="text-align:center">rt_device_open()</td> +<td style="text-align:center">打开传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_read()</td> +<td style="text-align:center">读取数据</td> +</tr> +<tr> +<td style="text-align:center">rt_device_control()</td> +<td style="text-align:center">控制传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_set_rx_indicate()</td> +<td style="text-align:center">设置接收回调函数</td> +</tr> +<tr> +<td style="text-align:center">rt_device_close()</td> +<td style="text-align:center">关闭传感器设备</td> +</tr> +</tbody> +</table> +<h6 id="313-aht10对接到sensor框架">3.1.3 AHT10对接到sensor框架 +</h6><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">SCL</td> +<td style="text-align:center">P512</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P511</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动-&gt;Enable I2C BUS-&gt;使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f301db2fd8e1988f2ca4e311c5d973cf.png" +loading="lazy" +alt="image-20220805110607476" +></p> +<p>然后使用下面的程序完成模块初始化工作</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;sensor_asair_aht10.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define AHT10_I2C_BUS &#34;i2c1&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 模块初始化工作 */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_aht10_port</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_sensor_config</span> <span class="n">cfg</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">dev_name</span> <span class="o">=</span> <span class="n">AHT10_I2C_BUS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">user_data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">AHT10_I2C_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_init</span><span class="p">(</span><span class="s">&#34;aht10&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_ENV_EXPORT</span><span class="p">(</span><span class="n">rt_hw_aht10_port</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>AHT10温湿度数据读取</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="c1">// AHT10设备读取数值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">aht10_device_t</span> <span class="n">dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_port</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">dev</span> <span class="o">=</span> <span class="nf">aht10_init</span><span class="p">(</span><span class="n">AHT10_I2C_BUS</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes failure&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes ok!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read humidity 采集湿度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="nf">aht10_read_humidity</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read temperature 采集温度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="nf">aht10_read_temperature</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="32-esp8266">3.2 ESP8266 +</h4><h6 id="321-底层uart简介">3.2.1 底层uart简介 +</h6><p>UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。</p> +<p>UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。</p> +<ul> +<li>串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。</li> +<li>异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。</li> +<li>数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5fdffba894c94d48a14c4f64a9992b93.jpeg" +loading="lazy" +alt="查看源图像" +></p> +<p>空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。</p> +<p>起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。</p> +<p>数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。<code>先发送最低位,最后发送最高位</code>,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。</p> +<h6 id="322-mqtt通讯协议介绍">3.2.2 MQTT通讯协议介绍 +</h6><p>MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quot;轻量级&quot;通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。</p> +<p>其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。</p> +<p>实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。</p> +<p><img src="https://img-blog.csdnimg.cn/a665ee8ebb4d427bbfa4c8a7ec013913.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h6 id="323-at组件">3.2.3 AT组件 +</h6><p>AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/1eb3c2cd78584efa85656a2cdd8daa8f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。</p> +<h6 id="324-mqtt协议及at组件在rt-thread中的使用">3.2.4 MQTT协议及AT组件在RT-Thread中的使用 +</h6><p><strong>RT-Thread Settings设置</strong></p> +<p>添加AT Device及OneNET软件包</p> +<p>AT Device配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf1c743b728c70c2764a3db1d368039c.png" +loading="lazy" +alt="image-20220805122341394" +></p> +<p>OneNET配置:</p> +<p>首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b40025d68d9bd0f32ff6efa3b74ff12d.png" +loading="lazy" +alt="image-20220805122741348" +> +<img src="https://img-blog.csdnimg.cn/img_convert/c7c17c8d743dca043a098be627baf93c.png" +loading="lazy" +alt="image-20220805122836636" +></p> +<p>然后将创建的信息填写到settings中</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9588bef3c3bf99d27bdc3cbd56394ece.png" +loading="lazy" +alt="image-20220805123248475" +></p> +<p>在组件中使能AT命令</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ad6b80e0d34df83a213dcdbf85d4416b.png" +loading="lazy" +alt="image-20220805123407687" +></p> +<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">TX</td> +<td style="text-align:center">P100</td> +</tr> +<tr> +<td style="text-align:center">RX</td> +<td style="text-align:center">P101</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">5V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p><strong>FSP配置</strong></p> +<p>由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置</p> +<p>首先点击<code>RA Smart Configurator</code>,记住这里使用的FSP版本为<code>v3.5.0</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/7710c9a62ad3a4486362f9d4bf92869f.png" +loading="lazy" +alt="image-20220805152204348" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2cb89487678dcf16bf3c784851a42091.png" +loading="lazy" +alt="image-20220805153017364" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf0866f3d50eae91f43aee142ef06966.png" +loading="lazy" +alt="image-20220805153317144" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/58fb0f18f54f0eaf49598c6c20f67b62.png" +loading="lazy" +alt="image-20220805153416015" +></p> +<p>完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现<code>#include &lt;dfs_posix.h&gt;</code>未参与编译以及还有其他一些问题,可以参考这一issue<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6188" target="_blank" rel="noopener" +>[CPK-RA6M4] onenet上云报错&lt;RT-Thread 的版本为 4.1.0 及以上&gt;</a></p> +<p>现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。</p> +<p>然后就是数据上云,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;temperature&#34;</span><span class="p">,</span><span class="n">temperature</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_delay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;humidity&#34;</span><span class="p">,</span><span class="n">humidity</span> <span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/096cd5faec78062ac227adcc12f08f05.png" +loading="lazy" +alt="image-20220805145942277" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67bd30c613f9a819cc2b7abddb58a5bc.png" +loading="lazy" +alt="image-20220805145958887" +></p> +<h4 id="33-rc522">3.3 RC522 +</h4><h6 id="331-底层spi协议简介">3.3.1 底层SPI协议简介 +</h6><p>SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9d4277d0aba7be84c59b68efb9402995.png" +loading="lazy" +alt="SPI 主设备和从设备的连接方式" +></p> +<ul> +<li>MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。</li> +<li>MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。</li> +<li>SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。</li> +<li>CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。</li> +</ul> +<p>整体的传输大概可以分为以下几个过程:</p> +<p>(1)主机先将<code>NSS</code>信号拉低,这样保证开始接收数据;</p> +<p>(2)当<strong>接收端</strong>检测到时钟的边沿信号时,它将立即读取<strong>数据线</strong>上的信号,这样就得到了一位数据(1<code>bit</code>;由于时钟是随数据一起发送的,因此指定<strong>数据的传输速度并不重要</strong>,尽管设备将具有可以运行的最高速度。</p> +<p>(3)<strong>主机</strong>发送到<strong>从机</strong>时:主机产生相应的时钟信号,然后数据<strong>一位一位</strong>地将从<code>MOSI</code>信号线上进行发送到从机;</p> +<p>(4)<strong>主机</strong>接收<strong>从机</strong>数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过<code>MISO</code>信号线发送;</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/3c32f25bed1d6e44c840608e4e352fc4.png" +loading="lazy" +alt="查看源图像" +></p> +<h6 id="332-rc522读卡机制说明">3.3.2 RC522读卡机制说明 +</h6><p>首先来看下RC522与M1卡的通讯流程:</p> +<p><strong>寻卡-&gt;防止卡片冲撞-&gt;选卡-&gt;休眠-&gt;发送0x40(7bit)-&gt;发送0x43-&gt;发送0xa0等4字节-&gt;发送0x00等18字节</strong></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/4c59b975aa9fdccbb19b38b059b87e1a.png" +loading="lazy" +alt="image-20220805154320392" +></p> +<ul> +<li> +<p>复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。</p> +</li> +<li> +<p>防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。</p> +</li> +<li> +<p>选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。</p> +</li> +<li> +<p>三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。</p> +</li> +<li> +<p>对数据块的操作: +读(Read):读一个块的数据; +写(Write):在一个块中写数据; +加(Increment):对数据块中的数值进行加值; +减(Decrement):对数据块中的数值进行减值; +传输(Transfer):将数据寄存器中的内容写入数据块中; +中止(Halt):暂停卡片的工作;</p> +</li> +</ul> +<h6 id="333-rc522在rt-thread的使用">3.3.3 RC522在RT-Thread的使用 +</h6><p>首先打开settings,添加RC522软件包,并在硬件部分使能SPI1</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ef7c08d20f957c70b67fe63943fec730.png" +loading="lazy" +alt="image-20220805155052783" +></p> +<p>打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/263c237d561d232466249aacb0dd42a4.png" +loading="lazy" +alt="image-20220805155448374" +></p> +<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">MOSI</td> +<td style="text-align:center">P411</td> +</tr> +<tr> +<td style="text-align:center">MISO</td> +<td style="text-align:center">P410</td> +</tr> +<tr> +<td style="text-align:center">SCL</td> +<td style="text-align:center">P412</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P311</td> +</tr> +<tr> +<td style="text-align:center">RST</td> +<td style="text-align:center">P312</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +<tr> +<td style="text-align:center">IRQ</td> +<td style="text-align:center">悬空</td> +</tr> +</tbody> +</table> +<p>代码部分参考RC522sample</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/474416ef76e9523302b9cdd544bbf03b.png" +loading="lazy" +alt="image-20220805155715593" +></p> +<p>SPI初始化配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;mfrc522.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_spi_device</span> <span class="n">mfrc522_spi_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">pin</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> <span class="n">spi_cs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_spi_rc522_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_err_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Attach Device +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span> <span class="o">=</span> <span class="n">MFRC522_SS_PIN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span> <span class="o">=</span> <span class="nf">rt_spi_bus_attach_device</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">,</span> <span class="n">MFRC522_SPI_BUS_NAME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">spi_cs</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[RC522] Failed to attach device %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Set device SPI Mode +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="n">rt_spi_configuration</span> <span class="n">cfg</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">data_width</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">RT_SPI_MASTER</span> <span class="o">|</span> <span class="n">RT_SPI_MODE_0</span> <span class="o">|</span> <span class="n">RT_SPI_MSB</span> <span class="o">|</span> <span class="n">RT_SPI_NO_CS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">max_hz</span> <span class="o">=</span> <span class="n">MFRC522_SPICLOCK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_spi_configure</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 导出到自动初始化 */</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_hw_spi_rc522_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>另外需要在完成一下配置,<code>双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5045a3933b508b5267b5fb9eeec6064b.png" +loading="lazy" +alt="image-20220805155922942" +></p> +<p>打开mfrc522.c,修改配置<code>MFRC522_SS_PIN</code>及<code>MFRC522_RST_PIN</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c61dba211ccb8ece988de9e703dc15cb.png" +loading="lazy" +alt="image-20220805161330936" +></p> +<p>打开rtconfig.h,找到以下两个引脚的定义,修改成如下:</p> +<p>注意:<strong><code>一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置</code></strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define MFRC522_SS_PIN 0x3b +</span></span><span class="line"><span class="cl">#define MFRC522_RST_PIN 0x3c +</span></span></code></pre></td></tr></table> +</div> +</div><p>至此,RC522的相关配置结束</p> +<h4 id="34-ssd1306">3.4 SSD1306 +</h4><h6 id="341-底层i2c通信协议">3.4.1 底层I2C通信协议 +</h6><p>(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)</p> +<h6 id="342-ssd1306在rt-thred的使用">3.4.2 SSD1306在RT-Thred的使用 +</h6><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">SCL</td> +<td style="text-align:center">P400</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P401</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>RT-Thread Settings配置:</p> +<p>添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c6b56810a69b472ea12eaa4e8d60008a.png" +loading="lazy" +alt="image-20220805162320450" +></p> +<p>打开rtconfig.h,添加i2c代码,<code>注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SCL_PIN 0x400 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SDA_PIN 0x401 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开drv_soft_i2c.c文件,添加代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define I2C0_BUS_CONFIG \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> { \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .scl = BSP_I2C0_SCL_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .sda = BSP_I2C0_SDA_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .bus_name = &#34;i2c0&#34;, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> } +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/04a3d96e15bbde106c73e389eca7fe10.png" +loading="lazy" +alt="image-20220805162941069" +></p> +<p>生成配置之后添加用户代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;ssd1306.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">25</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Hello RT-Thread!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_APP_EXPORT</span><span class="p">(</span><span class="n">oled_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实时时钟显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Now Time&#34;</span><span class="p">,</span> <span class="n">Font_16x26</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">40</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;:&#34;</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>温湿度数据显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Humi_Temp_Detection!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Temperature: %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Temperature_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Humidity:%d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">47</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Humidity_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4整体代码框架">4、整体代码框架 +</h2><h4 id="41-多线程任务分配">4.1 多线程任务分配 +</h4><p>本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。</p> +<p>所以共创建四个线程:</p> +<p>(1)RC522_thread:用于RC522读卡</p> +<p>(2)aht10_read_thread:用于aht10读取温湿度数值</p> +<p>(3)onenet_aht10_thread:云端数据上报</p> +<p>(4)oled_thread:OLED显示</p> +<h4 id="42-线程间交互">4.2 线程间交互 +</h4><p>本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。</p> +<h4 id="43-代码整合">4.3 代码整合 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/8aed1d64ef9fd8e219744b794b8dd048.png" +loading="lazy" +alt="image-20220802210559475" +></p> +<p>在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。</p> +<p>都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/36369721fa7745022aab2ad2492dc64f.png" +loading="lazy" +alt="image-20220805171602257" +></p> +<h2 id="5踩坑指南">5、踩坑指南 +</h2><p>其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:</p> +<p>(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为<code>v3.5.0</code></p> +<p>(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。</p> +<p>(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。</p> +<div class="video-wrapper"> +<iframe src="https://player.bilibili.com/player.html?as_wide=1&amp;high_quality=1&amp;page=1.8&bvid=BV1Ld4y1N7eo" +scrolling="no" +frameborder="no" +framespacing="0" +allowfullscreen="true" +> +</iframe> +</div>Study210利用SD运行流水灯程序https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post Study210利用SD运行流水灯程序" /><h2 id="1安装ecilpse">1.安装ecilpse +</h2><h4 id="1确认自己的pc机开发环境开发板光盘中有如下四个eclipse包">(1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包: +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_32.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_32.7z +</span></span></code></pre></td></tr></table> +</div> +</div><p>选择自己需求对应的安装包下载解压即可(<a class="link" href="https://download.csdn.net/download/qq_56914146/85162554" target="_blank" rel="noopener" +>此处可点击下载</a>)</p> +<h4 id="2配置好eclipse的环境变量">(2)配置好eclipse的环境变量 +</h4><p>借鉴<a class="link" href="https://blog.csdn.net/m0_46165586/article/details/107296429?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165018384616781685349830%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165018384616781685349830&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107296429.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=eclipse%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>Eclipse环境变量配置-超详细</a></p> +<h2 id="2开始工程的创建">2.开始工程的创建 +</h2><h4 id="1首先双击eclipseexe文件进入初次进入需要选择一个存储位置作为工程存放处workplace">(1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace) +</h4><h4 id="2建一个流水灯工程">(2)建一个流水灯工程 +</h4><p>首先在Project Explorer的空白栏右键单击-&gt;New-&gt;C Project +<img src="https://img-blog.csdnimg.cn/0b37eba37269446faf5de58793963da2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +项目名称填写LED_test +<img src="https://img-blog.csdnimg.cn/0b7cce5b3fa341f98792a316a1937054.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +点击next,finish</p> +<p>找到我们的项目工程示例,将全部文件复制到剪贴板 +<img src="https://img-blog.csdnimg.cn/2bbe14f0a69a46fe8328ce92f1492421.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键选择paste,选择粘贴全部 +<img src="https://img-blog.csdnimg.cn/842db416ea2c4929ac655d29bc4bfb07.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +这是粘贴好的文件项目 +<img src="https://img-blog.csdnimg.cn/d1dae4dddaf346b1be377c674fefdd35.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键Build Project或直接CTRL+B编译 +<img src="https://img-blog.csdnimg.cn/9389ca0a332143fdbfb650e41fb84f2b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 +<img src="https://img-blog.csdnimg.cn/776361da8d1045c3a39af79804bf0320.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +进入该目录下,可以发现生成了led.bin映像文件 +<img src="https://img-blog.csdnimg.cn/e497619b0ab74765aaffd33dc55be299.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="3下载源码到sd卡">3.下载源码到SD卡 +</h2><p>打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 +<img src="https://img-blog.csdnimg.cn/07008c13a27e41bebc960a47747c2283.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="4实例演示">4.实例演示 +</h2><h4 id="1清除开发板中的bootloader">(1)清除开发板中的bootloader +</h4><p>由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a>)</p> +<h4 id="2通过sd卡运行裸机程序">(2)通过SD卡运行裸机程序 +</h4><p>将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 +<img src="https://img-blog.csdnimg.cn/ddcba636b89841629cc4eba87b6a90b2.gif" +loading="lazy" +alt="在这里插入图片描述" +></p>Study210开发板刷安卓系统https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/Sat, 23 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/cover.jpg" alt="Featured image of post Study210开发板刷安卓系统" /><h2 id="一破坏bootloader">一、破坏BootLoader +</h2><blockquote> +<p>1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/c79baf4eb1e949c88d6bb50c32862354.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)</p> +</blockquote> +<blockquote> +<p>3.输入root(password:123456)</p> +</blockquote> +<blockquote> +<p>4.然后输入<code>busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync</code></p> +</blockquote> +<blockquote> +<p>5.回车后显示</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">1+0 records in +</span></span><span class="line"><span class="cl">1+O records out +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 +此时重新启动开发板就无法启动了</p> +</blockquote> +<h2 id="二sd卡刷机烧录uboot到sd卡中">二、SD卡刷机(烧录uboot到SD卡中) +</h2><blockquote> +<p>1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/958a8cf2a0554edd8e2d53d021490d4e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->此处如果SD烧写不成功,可尝试用管理员身份运行。 +<code>插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.</code></p> +<blockquote> +<p>2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)</p> +</blockquote> +<h2 id="三fastboot-下载安装镜像">三、fastboot 下载安装镜像 +</h2><blockquote> +<p>1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。</p> +</blockquote> +<blockquote> +<p>2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/bc1cb6ad4904482baaad59e05da074bc.png" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wex7LBk8-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415202849623.png)\]" +></p> +<blockquote> +<p>3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android</p> +</blockquote> +<blockquote> +<p><code>fastboot目录下应该包含的文件</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/850cde9ff40e4109a2b46cd186f93418.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p><code> Android中应该包含的文件(由于这里我烧写的是安卓系统)</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d97c6282c3ba46aba3a44b34a72e99a4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3DezB8H-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203108592.png)\]" +></p> +<blockquote> +<p>4.进行内核和系统的烧写 ,具体代码如下:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/eb401fcf50ec4f228025341cfcb28fca.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Dhso3IG-1650028395334)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203639928.png)\]" +></p> +<blockquote> +<p>同时在SecureCRT下可以看到下载结果</p> +</blockquote> +<blockquote> +<p>5.最后在windows控制台下输入<code> fastboot reboot</code>命令重启系统即可。</p> +</blockquote> +<h2 id="四dnw-刷机用fastboot刷android-">四、dnw 刷机(用fastboot刷Android ) +</h2><ul> +<li>准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/763acfc49ae34659b891a95ccd3de444.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaxHZTvW-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415204109660.png)\]" +></p> +<p>注意:</p> +<p>(1)安装<code>SecBulk.sys Njsmodi 2416 dnw drive</code>的驱动程序在<code>\X210V3S_A\tools\USB驱动\dnw_driver</code>下,安装驱动需要禁用数字签名(可参考<a class="link" href="https://blog.csdn.net/m0_37182543/article/details/80541418?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165002148616780271549615%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=165002148616780271549615&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-80541418.142%5ev9%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=Windows%E7%A6%81%E7%94%A8%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>win10如何永久关闭数字签名</a>)</p> +<p>(2)在使用dnw过程中需要长按电源键,否则会断开连接。</p> +<p>刷机步骤:</p> +<blockquote> +<p>1.将拨码开关拨到USB启动位置。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/51ddaa8b66494111899de8774b695007.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rua1zZN3-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415205448252.png)\]" +></p> +<blockquote> +<p>2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/63fbc995f8ab4752945842db148ad6a5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/170c0ec22ea4421daa7952994fdd3b0d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/e08d1f32d26d4558b078f85db271eab4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>3.(<code>同上操作</code>)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin</p> +</blockquote> +<blockquote> +<p><code> 注意!!!</code>:下载的同时要看<code>SecureCRT界面</code>,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。</p> +</blockquote> +<blockquote> +<p>4.回到secureCRT</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入fdisk -c 0 (进行分区) +</span></span><span class="line"><span class="cl">输入fastboot (查看分区) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/7676539a597a42d38993936ee760236a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<code>最后再输入</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fastboot -w +</span></span></code></pre></td></tr></table> +</div> +</div><p>全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。</p> +<p><img src="https://img-blog.csdnimg.cn/2982435176bb485abd152c2ab508d2cc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p>此文章参考于<a class="link" href="https://blog.csdn.net/madao1234/article/details/101104872" target="_blank" rel="noopener" +>S5PV210 Study210开发板刷系统</a></p>ART-Pi 网络时钟https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/cover.jpg" alt="Featured image of post ART-Pi 网络时钟" /><h2 id="玩转rt-thread自制网络时钟">《玩转RT-Thread》自制网络时钟 +</h2><hr> +<p>@[toc]</p> +<h2 id="一准备工作">一、准备工作 +</h2><ul> +<li> +<p>开发平台:RT-Thread Studio</p> +</li> +<li> +<p>开发板:ART-PI</p> +</li> +<li> +<p>主控芯片:STM32H750</p> +</li> +<li> +<p>温湿度传感器:SHT30</p> +</li> +<li> +<p>显示模组:0.96’OLED(SSD1306)</p> +</li> +<li> +<p>串口调试助手:SecureCRT</p> +</li> +</ul> +<p>注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。</p> +<h2 id="二新建rt-thread-项目">二、新建RT-Thread 项目 +</h2><p><img src="https://img-blog.csdnimg.cn/dfeff108ee0241919514065992e79ef8.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/9f49c13343914adf8d92f12a1ebf832e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="三获取温湿度数据">三、获取温湿度数据 +</h2><h4 id="1双击打开左边导航栏的rt-thread-setting">1、双击打开左边导航栏的RT-Thread Setting +</h4><p><img src="https://img-blog.csdnimg.cn/096e053c2ec545a9950c86dcb1e12d9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2使能软件模拟i2c单击点亮即可">2、使能软件模拟i2c(单击点亮即可) +</h4><p><img src="https://img-blog.csdnimg.cn/6bb6a362155641c0b0b6fa0953c60e45.png" +loading="lazy" +></p> +<h4 id="3配置i2c及相关引脚">3、配置i2c及相关引脚 +</h4><p><code>这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置</code></p> +<p><img src="https://img-blog.csdnimg.cn/ae8aaaa39cf04296809e01ccef73d980.png" +loading="lazy" +></p> +<h4 id="4添加sht3x软件包">4、添加SHT3X软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/d480f380b622466c9c38ae5129550067.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置,点击编译并下载</code></p> +<p>具体RT-Thread Studio的一般使用可参照<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124079730?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)</a></p> +<p><code>此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功</code></p> +<p><img src="https://img-blog.csdnimg.cn/04803141590e474bbe767242a8258ed5.png" +loading="lazy" +></p> +<p>此时在串口输入help,可以看出有一个sht3x配置</p> +<p><img src="https://img-blog.csdnimg.cn/bb9d35af5d19463282a1bd8400e90364.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入: +</span></span><span class="line"><span class="cl">sht3x probe i2c3 pd +</span></span><span class="line"><span class="cl">sht3x read(读取温湿度信息) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="四获取ntp时间">四、获取NTP时间 +</h2><h4 id="1使能选择wifi框架">1、使能选择WiFi框架 +</h4><p><img src="https://img-blog.csdnimg.cn/fac0022dff324acc9aa4a94e85407e69.png" +loading="lazy" +></p> +<h4 id="2使能ap6212库">2、使能AP6212库 +</h4><p><img src="https://img-blog.csdnimg.cn/97afeb11678140b2a5acbea44bc8937f.png" +loading="lazy" +></p> +<h4 id="3添加easyflash和netutils软件包">3、添加easyflash和netutils软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/08cda56d446541358d2b5038545ca284.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>鼠标右键netutils打开配置项</code></p> +<p><img src="https://img-blog.csdnimg.cn/cd98d8f9bb0f4f15941c4617c32b7aa3.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>使能NTP (网络时间协议)客户端 </code></p> +<p><img src="https://img-blog.csdnimg.cn/7fe0c1a627d94d1dba87dbcf4918d127.png" +loading="lazy" +></p> +<p><code>使能软件模拟RTC</code></p> +<p><img src="https://img-blog.csdnimg.cn/f2ac26826c0a463bb1124804fcc7c563.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置</code></p> +<p><code>修改配置</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cassandra" data-lang="cassandra"><span class="line"><span class="cl"><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="err">打开电脑中项目所在的路径</span><span class="o">-</span><span class="n">workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">packages</span><span class="o">-</span><span class="n">EasyFlash</span><span class="o">-</span><span class="n">v4</span><span class="err">.1.0</span><span class="o">-</span><span class="n">port</span><span class="err">,将</span><span class="n">port目录下的ef_fal_port</span><span class="p">.</span><span class="n">c文件复制到workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">board</span><span class="o">-</span><span class="n">port中</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="err">修改</span><span class="n">port中宏定义FAL_EF_PART_NAME</span><span class="w"> </span><span class="err">中的名字</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">#</span><span class="n">define</span><span class="w"> </span><span class="n">FAL_EF_PART_NAME</span><span class="w"> </span><span class="s">&#34;easyflash&#34;</span><span class="w"> </span><span class="c1">//修改后的宏定义 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>此时再编译并下载到开发板中</code></p> +<h4 id="4连接wifi">4、连接WiFi +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">wifi</span> <span class="n">scan</span> <span class="c1">//搜索wifi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">wifi</span> <span class="n">join</span> <span class="p">[</span><span class="n">SSID</span><span class="p">]</span> <span class="p">[</span><span class="n">PASSWORD</span><span class="p">]</span> <span class="c1">//连接WiFi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="nl">SSID</span><span class="p">:</span><span class="n">WiFi名称</span> +</span></span><span class="line"><span class="cl"><span class="n">PASSWORD</span><span class="err">:</span><span class="n">WiFi密码</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5设置开机自连接wifi">5、设置开机自连接WiFi +</h4><p><code>(1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_WIFI +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_mgnt.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_cfg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_prot.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;easyflash.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;fal.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#if (EF_SW_VERSION_NUM &lt; 0x40000) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">base64_table</span><span class="p">[</span><span class="mi">65</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="mi">256</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3E</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3F</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x34</span><span class="p">,</span> <span class="mh">0x35</span><span class="p">,</span> <span class="mh">0x36</span><span class="p">,</span> <span class="mh">0x37</span><span class="p">,</span> <span class="mh">0x38</span><span class="p">,</span> <span class="mh">0x39</span><span class="p">,</span> <span class="mh">0x3A</span><span class="p">,</span> <span class="mh">0x3B</span><span class="p">,</span> <span class="mh">0x3C</span><span class="p">,</span> <span class="mh">0x3D</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0A</span><span class="p">,</span> <span class="mh">0x0B</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x0D</span><span class="p">,</span> <span class="mh">0x0E</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x10</span><span class="p">,</span> <span class="mh">0x11</span><span class="p">,</span> <span class="mh">0x12</span><span class="p">,</span> <span class="mh">0x13</span><span class="p">,</span> <span class="mh">0x14</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x16</span><span class="p">,</span> <span class="mh">0x17</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="mh">0x19</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0x1B</span><span class="p">,</span> <span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x1D</span><span class="p">,</span> <span class="mh">0x1E</span><span class="p">,</span> <span class="mh">0x1F</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="mh">0x21</span><span class="p">,</span> <span class="mh">0x22</span><span class="p">,</span> <span class="mh">0x23</span><span class="p">,</span> <span class="mh">0x24</span><span class="p">,</span> <span class="mh">0x25</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0x27</span><span class="p">,</span> <span class="mh">0x28</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x29</span><span class="p">,</span> <span class="mh">0x2A</span><span class="p">,</span> <span class="mh">0x2B</span><span class="p">,</span> <span class="mh">0x2C</span><span class="p">,</span> <span class="mh">0x2D</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x2F</span><span class="p">,</span> <span class="mh">0x30</span><span class="p">,</span> <span class="mh">0x31</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0x33</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pos</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">end</span><span class="p">,</span> <span class="o">*</span><span class="n">in</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">olen</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">=</span> <span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="cm">/* 3-byte blocks to 4-byte */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">+=</span> <span class="n">olen</span> <span class="o">/</span> <span class="mi">72</span><span class="p">;</span> <span class="cm">/* line feeds */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span><span class="o">++</span><span class="p">;</span> <span class="cm">/* nul termination */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">end</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span> <span class="o">+</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pos</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">6</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x3f</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * return: length, 0 is error. +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">input_length</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">out_len</span> <span class="o">=</span> <span class="n">input_length</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">input_length</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_a</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_b</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_c</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_d</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">triple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sextet_a</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_b</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_c</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_d</span> <span class="o">&lt;&lt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">6</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_info</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">,</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">),</span> <span class="n">buff</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_len</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">wlan_cfg_len</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">base64_buf</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">base64_buf</span> <span class="o">=</span> <span class="nf">rt_malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span> <span class="cm">/* 3-byte blocks to 4-byte, and the end. */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">base64_buf</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* (EF_SW_VERSION_NUM &lt; 0x40000) */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">rt_wlan_cfg_ops</span> <span class="n">ops</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_cfg</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">get_len</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_cfg</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">easyflash_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_set_ops</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ops</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_cache_refresh</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在main.c中添加自动连接函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define LED_PIN GET_PIN(I, 8) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* init Wi-Fi auto connect feature */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* enable auto reconnect on WLAN device */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。</code></p> +<h2 id="五oled屏显示温湿度和实时时间信息">五、OLED屏显示温湿度和实时时间信息 +</h2><h4 id="1添加u8g2软件包">1、添加u8g2软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/9aa5ecc3b3484b14b1c57ef4c75aae73.png" +loading="lazy" +></p> +<h4 id="2编写oled_display显示线程">2、编写oled_display显示线程 +</h4><p><code>(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。</code></p> +<p><code>代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rthw.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;U8g2lib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;drv_soft_i2c.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sht3x.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">sht3x_device_t</span> <span class="nf">sht3x_init</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">i2c_bus_name</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">sht3x_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="nf">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device_t</span> <span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define OLED_I2C_PIN_SCL 24 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define OLED_I2C_PIN_SDA 25 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">U8G2_SSD1306_128X64_NONAME_F_SW_I2C</span> <span class="nf">u8g2</span><span class="p">(</span><span class="n">U8G2_R0</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* clock=*/</span> <span class="n">OLED_I2C_PIN_SCL</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* data=*/</span> <span class="n">OLED_I2C_PIN_SDA</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* reset=*/</span> <span class="n">U8X8_PIN_NONE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define SUN 0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SUN_CLOUD 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define CLOUD 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RAIN 3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define THUNDER 4 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeatherSymbol</span><span class="p">(</span><span class="n">u8g2_uint_t</span> <span class="n">x</span><span class="p">,</span> <span class="n">u8g2_uint_t</span> <span class="n">y</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// fonts used: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_embedded_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_weather_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">69</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN_CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">65</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">64</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">RAIN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">THUNDER</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_embedded_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeather</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">degree</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">degree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawHumidity</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">humidity</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;%&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">48</span><span class="o">+</span><span class="mi">3</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;Hi~&#34;</span><span class="p">);</span> <span class="c1">// requires enableUTF8Print() +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_6x13_tr</span><span class="p">);</span> <span class="c1">// choose a suitable font +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s">&#34;By Mculover666&#34;</span><span class="p">);</span> <span class="c1">// write something to the internal memory +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device_t</span> <span class="n">sht3x_device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device</span> <span class="o">=</span> <span class="n">sht3x_init</span><span class="p">(</span><span class="s">&#34;i2c3&#34;</span><span class="p">,</span> <span class="mh">0x44</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">mstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">hstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">time_t</span> <span class="n">now</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="nc">tm</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">min</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">hour</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">0</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">(</span><span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">=</span><span class="n">gmtime</span><span class="p">((</span><span class="k">const</span> <span class="n">time_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">now</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">hour</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_hour</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">min</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_min</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">min</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">hour</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">firstPage</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">do</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso42_tn</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">hstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="s">&#34;:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">67</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">mstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span> <span class="n">u8g2</span><span class="p">.</span><span class="n">nextPage</span><span class="p">()</span> <span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">1</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeather</span><span class="p">(</span><span class="n">SUN</span><span class="p">,</span> <span class="n">temperature</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">2</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">humidity</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawHumidity</span><span class="p">(</span><span class="n">RAIN</span><span class="p">,</span> <span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">oled_display</span><span class="p">,</span> <span class="n">oled</span> <span class="n">start</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在 applications 文件夹下创建oled_display.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* APPLICATIONS_OLED_DISPLAY_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(3)最终的主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2020, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2020-09-02 RT-Thread first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">oled_display</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/*-------------------------- I2C CONFIG BEGIN --------------------------*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C1_SCL_PIN 24 </span><span class="c1">// p2 10 PB8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C1_SDA_PIN 25 </span><span class="c1">// p2 7 PB9 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C3_SCL_PIN 119 </span><span class="c1">//p1 29 PH7 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C3_SDA_PIN 120 </span><span class="c1">//p1 28 PH8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/*-------------------------- UART CONFIG END --------------------------*/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六实验展示">六、实验展示 +</h2><p><img src="https://img-blog.csdnimg.cn/c0cbf5357ce14d7d963684d4338eee9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/d329c18ee11d45a59252f42bb043663b.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/99f00b0cf72b4e20a0697914e7048f97.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="七问题总结">七、问题总结 +</h2><p><code>注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// cpp函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。</code></p> +<hr> +<p>这次的分享就到这里,有相关问题的欢迎留言私信!</p>ifconfig不显示ip地址https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/cover.jpg" alt="Featured image of post ifconfig不显示ip地址" /><h4 id="ubuntu终端下命令ifconfig的问题解决">ubuntu终端下命令ifconfig的问题解决 +</h4><blockquote> +<p>问题一. ifconfig之后只显示lo,没有看到eth0 +问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 +问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<h4 id="问题一ifconfig之后只显示lo没有看到eth0-">问题一:ifconfig之后只显示lo,没有看到eth0 ? +</h4><blockquote> +<p>1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 +ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback +这边的设置是本地回路。在后面加上</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">iface eth0 inet static +</span></span><span class="line"><span class="cl">address 192.168.1.230 //(ip地址) +</span></span><span class="line"><span class="cl">netmask 255.255.255.0 //(子网掩码) +</span></span><span class="line"><span class="cl">gateway 192.168.1.1 //(网关) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。</p> +</blockquote> +<blockquote> +<p>2.eth0被关了 +输入命令行:ifconfig eth0 up #开启eth0</p> +</blockquote> +<hr> +<h4 id="问题二ifconfig之后显示eth0但是没有显示inet地址广播掩码-">问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”? +</h4><blockquote> +<p>1.先用sudo dhclient eth0更新IP地址 +2.然后运行sudo ifconfig eth0 +3.reboot</p> +</blockquote> +<hr> +<h4 id="问题三重启后ping命令不能使用因为dns还没设置编辑etcresolvconf加上dns服务器地址">问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。 +</h4><blockquote> +<p>设置好后,如果直接ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<pre><code>nameserver 8.8.8.8 +nameserver 8.8.4.4 +</code></pre> +<blockquote> +<p>这两个是Google提供的免费DNS服务器的IP地址</p> +</blockquote>x210开发板 虚拟驱动创建流程https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/cover.jpg" alt="Featured image of post x210开发板 虚拟驱动创建流程" /><h2 id="内核编译常用命令">内核编译常用命令 +</h2><p>安装模块 +<code>lsmod module_test.ko</code> +创建设备文件 +<code>mknod /dev/test c 250 0</code> +查看设备状态 +<code>lsmod module_test.ko</code> +查看设备注册信息(分为字符设备和块设备) +<code>cat /proc/devices</code></p> +<h2 id="知识补充">知识补充: +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span><span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">j</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:这里如果没有指定i值,则打印出来的是随机值 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 如果定义一个静态变量而没有赋值,则打印默认为0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="虚拟驱动创建流程">虚拟驱动创建流程 +</h2><p>首先进入x210_bsp/kernel</p> +<p>make menuconfig</p> +<p><img src="https://img-blog.csdnimg.cn/783c09aa06cb4a83a4df08d76d31c447.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/dc736c9d0d2b4ceaaaffcd6f90a1a16a.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/1193fb6e02be4c52a1d5951b0236ff38.png" +loading="lazy" +></p> +<p>make -j4</p> +<p>cp arch/arm/boot/zImage /tftpboot/ -f</p> +<p>重启开发板查看开发板设备</p> +<p>ls /sys/devices/platform/</p> +<p><img src="https://img-blog.csdnimg.cn/f57e4a58658e4380967bbfa1c0813864.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2f3b1acd43e740e68774ecbe2824ea2f.png" +loading="lazy" +></p> +<p>cd sys/class/leds</p> +<p>led_test_4编写完成后</p> +<p>编译不报错即可</p> +<p>cd /root/x210_bsp/kernel/drivers/leds/</p> +<p>cp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./</p> +<p>vi Makefile-&gt;</p> +<p><code>obj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o</code></p> +<p><img src="https://img-blog.csdnimg.cn/b30ce84418064d24a4e01c96218834f2.png" +loading="lazy" +></p> +<p>vi Kconfig更改依赖(添加以下文件)</p> +<p><code>config LEDS_S5PV210 tristate &quot;LED Support for S5PV210&quot; help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.</code></p> +<p><img src="https://img-blog.csdnimg.cn/43715e94bbcb4e8ab850492c919afc33.png" +loading="lazy" +></p> +<p>进入到x210_bsp/kernel</p> +<p>执行make menuconfig</p> +<p>可以发现生成了新的配置(Device Drivers-&gt; LED_Support),使能这个</p> +<p><img src="https://img-blog.csdnimg.cn/31b19678d8204209b05d62de54afd1d9.png" +loading="lazy" +></p> +<p>执行make编译</p> +<p><code> cp arch/arm/boot/zImage /tftpboot/ -f</code></p> +<p>secureCRT:</p> +<p>cd sys/class/leds</p> +<p>进入LED1,执行</p> +<p>echo 1 &gt; brightness // 灯亮</p> +<p>echo 0 &gt; brightness //灯灭</p> +<hr> +<p>最后附上源代码:</p> +<p><code>leds-s5pv210.c</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/module.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/init.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/fs.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/uaccess.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio-bank.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/regs-gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/ioport.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/io.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/cdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/device.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/leds.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED1 S5PV210_GPJ0(3) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED2 S5PV210_GPJ0(4) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED3 S5PV210_GPJ0(5) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_OFF 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_ON 0 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led1_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led1_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led2_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led2_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led3_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led3_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">s5pv210_led_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 申请GPIO +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="nf">gpio_request</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="s">&#34;led1_gpj0.3&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;gpio_request failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_direction_output</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led1&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led1_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led2&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led2_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led3&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led3_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">s5pv210_led_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">module_init</span><span class="p">(</span><span class="n">s5pv210_led_init</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">module_exit</span><span class="p">(</span><span class="n">s5pv210_led_exit</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_LICENSE</span><span class="p">(</span><span class="s">&#34;GPL&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_AUTHOR</span><span class="p">(</span><span class="s">&#34;WYQ&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_DESCRIPTION</span><span class="p">(</span><span class="s">&#34;module_test&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>Makefile</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#KERN_VER = $(shell uname -r) +</span></span></span><span class="line"><span class="cl"><span class="cp">#KERN_DIR = /lib/modules/$(KERN_VER)/build +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">KERN_DIR</span> <span class="o">=</span> <span class="o">/</span><span class="n">root</span><span class="o">/</span><span class="n">x210_bsp</span><span class="o">/</span><span class="n">kernel</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">obj</span><span class="o">-</span><span class="n">m</span> <span class="o">+=</span> <span class="n">leds</span><span class="o">-</span><span class="n">s5pv210</span><span class="p">.</span><span class="n">o</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">all</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nl">PHONY</span><span class="p">:</span><span class="n">clean</span> +</span></span><span class="line"><span class="cl"><span class="nl">clean</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> <span class="n">clean</span> +</span></span></code></pre></td></tr></table> +</div> +</div>线程间同步 信号量https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/Sun, 17 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/cover.jpg" alt="Featured image of post 线程间同步 信号量" /><h2 id="一概述">一、概述: +</h2><blockquote> +<p>多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:</p> +</blockquote> +<p><strong>信号量</strong>(semaphore)、<strong>互斥量</strong>(mutex)、和<strong>事件集</strong>(event)</p> +<h2 id="二信号量">二、信号量 +</h2><h4 id="1简述">1、简述 +</h4><p>信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到<code>同步</code>或<code>互斥</code>的目的。</p> +<p>信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当<code>信号量实例数目为零时</code>,再申请该信号量的线程就会被<code>挂起</code>在该信号量的等待队列上,等待可用的信号量实例(资源)。</p> +<p><img src="https://img-blog.csdnimg.cn/55d38f32e6e84b038d35a27bea1b9074.png" +loading="lazy" +></p> +<h4 id="2信号量结构体">2、信号量结构体 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_ipc_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; 继承自ipc_object类 */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">value</span><span class="p">;</span> <span class="cm">/**&lt; value of semaphore. */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">reserved</span><span class="p">;</span> <span class="cm">/**&lt; reserved field 预留*/</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。</p> +<h4 id="3信号量使用及管理">3、信号量使用及管理 +</h4><blockquote> +<p>对一个信号量的操作包含:<code>创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量</code>。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d8bde585ecaa4669817d29f0ffdc34f5.png" +loading="lazy" +></p> +<p>1)动态创建信号量</p> +<blockquote> +<p>当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。</p> +</blockquote> +<blockquote> +<p>当选择 <code>RT_IPC_FLAG_FIFO(先进先出)</code>方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; +当选择 <code>RT_IPC_FLAG_PRIO(优先级等待)</code>方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。</p> +</blockquote> +<p><code>函数声明</code>:</p> +<p><code>rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);</code></p> +<p><code>参数介绍</code>:</p> +<p><img src="https://img-blog.csdnimg.cn/f829de152967470393d8b7605e4c2b12.png" +loading="lazy" +></p> +<p><code>注意:</code></p> +<p><code>(1)此处的*name定义最多只能显示八个字符</code></p> +<p><code>(2)查看rt_sem_create()函数返回值是--&gt;typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore </code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// flag值 如下 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_FIFO 0x00 </span><span class="cm">/**&lt; FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_PRIO 0x01 </span><span class="cm">/**&lt; PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>2)动态创建的信号量删除</p> +<blockquote> +<p>系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。</p> +</blockquote> +<blockquote> +<p>调用这个函数时,系统将删除这个信号量。<code>如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。</code></p> +</blockquote> +<p><code>函数声明</code> +<code>rt_err_t rt_sem_delete(rt_sem_t sem);</code></p> +<p><code>实例</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)静态创建信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">value</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<p><img src="https://img-blog.csdnimg.cn/cbe2c704ffc849cf8859a6c46237681a.png" +loading="lazy" +></p> +<p>4)脱离信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于<code>静态初始化的信号量</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_detach</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>5)获取信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。</p> +<p>如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择<code>直接返回、或挂起等待一段时间、或永久等待</code>,直到其他线程或中断释放该信号量。</p> +<p>如果在参数 time 指定的时间内依然得不到信号量,线程将<code>超时返回</code>,返回值是<code> - RT_ETIMEOUT</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_take</span> <span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> <span class="kt">rt_int32_t</span> <span class="n">time</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// time参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_FOREVER -1 </span><span class="cm">/**&lt; Block forever until get resource. */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_NO 0 </span><span class="cm">/**&lt; Non-block. */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 扩展: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_trytake</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> <span class="c1">// 无等待获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>6)信号量释放</p> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>描述</code></p> +<blockquote> +<p>例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。</p> +</blockquote> +<h4 id="4信号量实例演示">4、信号量实例演示 +</h4><blockquote> +<p>这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/632591398002468c9a69cf3e4ac8cfe4.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/4293c61a10d14a128312fd50d7d2c9c6.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>查看信号量设定的标志位是<code>RT_IPC_FLAG_FIFO</code>,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1-&gt;线程2-&gt;线程1-&gt;线程2&hellip;的顺序执行的,这样就实现了线程的并发互斥运行。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1000730483a345728f1faa2ba68bde2d.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/31c3f295be2e41f9ab8d674ade353007.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>最后附上测试源代码</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> <span class="n">sem2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1</span><span class="p">,</span><span class="n">th2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th1_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">8000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="n">sem1</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">100</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th1_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="n">sem1</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="s">&#34;sem2&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_init successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th1</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th1&#34;</span><span class="p">,</span> <span class="n">th1_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th2</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th2&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th2</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>ubuntu彻底删除通过apt方式安装的程序https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post ubuntu彻底删除通过apt方式安装的程序" /><p>以删除apache2为例,其它程序也都是这么删&hellip;<br> +1.先通过apt删除程序和相关配置文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>2.自动删除不使用的软件包</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get autoremove +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.找出与apache2相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dpkg --get-selections|grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>没有就不显示,如果有就删除这些相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove xxx +</span></span></code></pre></td></tr></table> +</div> +</div><p>4.查看apache2是否还有进程存在</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ps -ef |grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果有就杀掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo kill -9 8888 //后面接pid号码,用空格隔开 +</span></span></code></pre></td></tr></table> +</div> +</div><p>5.全局查找和apache2相关的文件,需要一定时间,稍等</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo find / -name apache2* +</span></span></code></pre></td></tr></table> +</div> +</div><p>将找到的文件逐个删掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo rm -rf /usr/share/bash-completion/completions/apache2ctl +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就彻底删除掉apache2了</p>线程管理https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 线程管理" /><p>原理实战请查看<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124539095" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)</a></p> +<h1 id="一序言">一、序言 +</h1><p>在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 +同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。</p> +<p>下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:</p> +<blockquote> +<p>1.读取数据 +2.显示数据</p> +</blockquote> +<p>简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 +<img src="https://img-blog.csdnimg.cn/6d57696f2ffc4e859bf8c8c1ffc0789e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +在RT-Thread 中,与上述子任务对应的程序实体就是线程,<code>线程是实现任务的载体</code>。 +它是RT-Thread中<code>最基本的调度单位</code>,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的<code>优先级</code>,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 +<code>上下文:</code>当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。</p> +<h1 id="二线程管理的功能特点">二、线程管理的功能特点 +</h1><p>RT-Thread 线程管理的主要功能是<code>对线程进行管理和调度</code>,系统中总共存在两类线程,分别是<code>系统线程</code>和<code>用户线程</code>。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。</p> +<p>如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 +<img src="https://img-blog.csdnimg.cn/5584a47897de430597897d3a6bddd710.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>RT-Thread 的线程调度器是<code>抢占式</code>的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。</li> +<li>当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。</li> +<li>当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(<code>详细内容可参考</code><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124145153" target="_blank" rel="noopener" +>【操作系统】进程上下文和线程上下文</a>)信息恢复。</li> +</ul> +<h1 id="三线程的工作机制">三、线程的工作机制 +</h1><h2 id="1线程控制块">1.线程控制块 +</h2><p>在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* 线程控制块*/ +</span></span><span class="line"><span class="cl">struct rt_thread +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* rt 对象*/ +</span></span><span class="line"><span class="cl"> char name[RT_NAME_MAX]; /* 线程名称*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t type; /* 对象类型*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t flags; /* 标志位*/ +</span></span><span class="line"><span class="cl"> rt_list_t list; /* 对象列表*/ +</span></span><span class="line"><span class="cl"> rt_list_t tlist; /* 线程列表*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 栈指针与入口指针*/ +</span></span><span class="line"><span class="cl"> void *sp; /* 栈指针*/ +</span></span><span class="line"><span class="cl"> void *entry; /* 入口函数指针*/ +</span></span><span class="line"><span class="cl"> void *parameter; /* 参数*/ +</span></span><span class="line"><span class="cl"> void *stack_addr; /* 栈地址指针*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t stack_size; /* 栈大小*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 错误代码*/ +</span></span><span class="line"><span class="cl"> rt_err_t error; /* 线程错误代码*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t stat; /* 线程状态*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t current_priority; /* 当前优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t init_priority; /* 初始优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t number_mask; +</span></span><span class="line"><span class="cl"> ...... +</span></span><span class="line"><span class="cl"> rt_ubase_t init_tick; /* 线程初始化计数值*/ +</span></span><span class="line"><span class="cl"> rt_ubase_t remaining_tick; /* 线程剩余计数值*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> struct rt_timer thread_timer; /* 内置线程定时器*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t user_data; /* 用户数据*/ +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code> 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。</code></li> +<li><code>cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。</code></li> +<li><code>最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。</code></li> +</ul> +<h2 id="2线程的重要属性">2.线程的重要属性 +</h2><h4 id="1-线程栈">(1) 线程栈 +</h4><ul> +<li>RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。</li> +<li>线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。</li> +<li>对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。</li> +<li>线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 +<img src="https://img-blog.csdnimg.cn/041732b5e1fd43d5a62382931ad50360.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></li> +</ul> +<h4 id="2-线程状态">(2) 线程状态 +</h4><p>线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 +在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:</p> +<table> +<thead> +<tr> +<th>状态</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>初始态</td> +<td>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</td> +</tr> +<tr> +<td>就绪态</td> +<td>在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY</td> +</tr> +<tr> +<td>运行态</td> +<td>线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING</td> +</tr> +<tr> +<td>挂起态</td> +<td>也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND</td> +</tr> +<tr> +<td>关闭态</td> +<td>当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE</td> +</tr> +</tbody> +</table> +<h4 id="3-线程优先级">(3) 线程优先级 +</h4><ul> +<li> +<p>RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。</p> +</li> +<li> +<p>RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。</p> +</li> +</ul> +<h4 id="4-时间片">(4) 时间片 +</h4><blockquote> +<p>每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。</p> +</blockquote> +<p>假设有2 个<code>优先级相同的就绪态线程A 与B</code>,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 +<img src="https://img-blog.csdnimg.cn/31c4fb41bf8947c1a47864b12b9e602e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5-线程的入口函数">(5) 线程的入口函数 +</h4><p>线程控制块中的<code>entry</code>是线程的入口函数,它是线程实现预期功能的函数。</p> +<p>线程的入口函数由用户设计实现,一般有以下两种代码形式: +1.<code>无限循环模式</code></p> +<blockquote> +<p>在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 +界事件的发生,而后进行相应的服务:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void thread_entry(void* paramenter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">while (1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> /* 等待事件的发生*/ +</span></span><span class="line"><span class="cl"> /* 对事件进行服务、进行处理*/ +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 +所以在实时操作系统中必须注意的一点就是:<!-- raw HTML omitted -->线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。<!-- raw HTML omitted --></p> +</blockquote> +<p>2.<code>顺序执行或有限次循环模式</code></p> +<blockquote> +<p>如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">static void thread_entry(void* parameter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* 处理事务#1 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#2 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#3 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6-常见的线程错误码">(6) 常见的线程错误码 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_EOK 0 /* 无错误*/ +</span></span><span class="line"><span class="cl">#define RT_ERROR 1 /* 普通错误*/ +</span></span><span class="line"><span class="cl">#define RT_ETIMEOUT 2 /* 超时错误*/ +</span></span><span class="line"><span class="cl">#define RT_EFULL 3 /* 资源已满*/ +</span></span><span class="line"><span class="cl">#define RT_EEMPTY 4 /* 无资源*/ +</span></span><span class="line"><span class="cl">#define RT_ENOMEM 5 /* 无内存*/ +</span></span><span class="line"><span class="cl">#define RT_ENOSYS 6 /* 系统不支持*/ +</span></span><span class="line"><span class="cl">#define RT_EBUSY 7 /* 系统忙*/ +</span></span><span class="line"><span class="cl">#define RT_EIO 8 /* IO 错误*/ +</span></span><span class="line"><span class="cl">#define RT_EINTR 9 /* 中断系统调用*/ +</span></span><span class="line"><span class="cl">#define RT_EINVAL 10 /* 非法参数*/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3线程状态切换">3.线程状态切换 +</h2><p>RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: +<img src="https://img-blog.csdnimg.cn/3c79cc6198144f02b4830d4521384c30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<ul> +<li>线程通过调用函数<code>rt_thread_create/init()</code> 进入到初始状态<code>(RT_THREAD_INIT)</code>;</li> +<li>初始状态的线程通过调用函数<code>rt_thread_startup()</code> 进入到就绪状态<code>(RT_THREAD_READY)</code>;</li> +<li>就绪状态的线程被调度器调度后进入运行状态<code>(RT_THREAD_RUNNING)</code>;</li> +<li>当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态<code>(RT_THREAD_SUSPEND)</code>;</li> +</ul> +</blockquote> +<blockquote> +<ul> +<li>处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。</li> +<li>挂起状态的线程,如果调用<code>rt_thread_delete/detach() </code>函数,将更改为关闭状态<code>(RT_THREAD_CLOSE)</code>;</li> +<li>而运行状态的线程,如果运行结束,就会在线程的最后部分执行<code>rt_thread_exit() </code>函数,将状态更改为关闭状态。</li> +</ul> +</blockquote> +<p><!-- raw HTML omitted --><code>!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。</code></p> +<h2 id="4系统线程">4.系统线程 +</h2><p>系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。</p> +<h4 id="1空闲线程">(1)空闲线程 +</h4><p><code>空闲线程</code>是系统创建的最低优先级的线程,线程状态<code>永远为就绪态</code>。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。</p> +<p>另外,空闲线程在RT-Thread 也有着它的特殊用途:</p> +<ul> +<li>若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。</li> +<li>空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>钩子函数</a>和<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5ev7%5earticle_score_rank,157%5ev4%5econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>看门狗</a>不懂的可以看这里)</li> +</ul> +<h4 id="2-主线程">(2) 主线程 +</h4><p>在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。</p> +<p>过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 +<img src="https://img-blog.csdnimg.cn/b08911ca57334476945d473ab814f006.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="四线程的管理方式">四、线程的管理方式 +</h1><p>可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。</p> +<p>动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。</p> +<p>下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 +<img src="https://img-blog.csdnimg.cn/fea91f8134b648ccaefeb5cf201de15f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="1创建和删除线程">1.创建和删除线程 +</h2><h4 id="1创建线程">(1)创建线程 +</h4><p>一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_thread_t</span> <span class="n">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。</p> +</blockquote> +<p>线程创建rt_thread_create() 的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/f1ba4c76de384fcc91060025bff4bef7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2删除线程">(2)删除线程 +</h4><p>对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:</p> +<pre><code>rt_err_t rt_thread_delete(rt_thread_t thread); +</code></pre> +<p>调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。</p> +<p>线程删除rt_thread_delete() 接口的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/eb9a07efdd95454c8873506f5178d1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。</code></p> +<h2 id="2初始化和脱离线程">2.初始化和脱离线程 +</h2><h4 id="1初始化线程">(1)初始化线程 +</h4><p><code>线程的初始化</code>可以使用下面的函数接口完成,来初始化静态线程对象:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="n">rt_thread_init</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="n">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/c1e6ca6ef6b84ebe93d0888ff71332af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2脱离线程">(2)脱离线程 +</h4><p>对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:</p> +<pre><code>rt_err_t rt_thread_detach (rt_thread_t thread); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>thread</td> +<td>线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT_EOK</td> +<td>线程脱离成功</td> +</tr> +<tr> +<td>-RT_ERROR</td> +<td>线程脱离失败</td> +</tr> +</tbody> +</table> +<h2 id="3启动线程">3.启动线程 +</h2><p>创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:</p> +<pre><code>rt_err_t rt_thread_startup(rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/431f38ae0feb46dc833f9835ec57577e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 +动的线程优先级比当前线程优先级高,将立刻切换到这个线程。</p> +</blockquote> +<h2 id="4获得当前线程">4.获得当前线程 +</h2><p>在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:</p> +<pre><code>rt_thread_t rt_thread_self(void); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/33c1e79ddc8b42c0a28237a91e67b92c.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="5使线程出让处理器资源">5.使线程出让处理器资源 +</h2><blockquote> +<p>当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。</p> +</blockquote> +<p>线程让出处理器使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_yield(void); +</code></pre> +<blockquote> +<p>调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。</p> +</blockquote> +<h2 id="6使线程睡眠">6.使线程睡眠 +</h2><blockquote> +<p>在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。</p> +</blockquote> +<p>线程睡眠可使用以下三个函数接口:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_thread_sleep(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_delay(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_mdelay(rt_int32_t ms); +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/6ebefaeea61f48a7b26d43e0d6589055.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="7挂起和恢复线程">7.挂起和恢复线程 +</h2><h4 id="1线程挂起">(1)线程挂起 +</h4><blockquote> +<ul> +<li>当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。</li> +<li>处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。</li> +</ul> +</blockquote> +<p><code>线程挂起</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_suspend (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/eed2dcfd794040798637c029b253fb87.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。</code></p> +<h4 id="2恢复线程">(2)恢复线程 +</h4><blockquote> +<p>恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 +所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。</p> +</blockquote> +<p><code>线程恢复</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_resume (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/0640fc789a1645d3b424f605d3aca937.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="8控制线程">8.控制线程 +</h2><p>当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:</p> +<pre><code>rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/348eb561864549528d9695d8f504af92.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<pre><code>指示控制命令cmd 当前支持的命令包括: +•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级; +•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用; +•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。 +</code></pre> +<h2 id="设置和删除空闲钩子">设置和删除空闲钩子 +</h2><blockquote> +<p>空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。</p> +</blockquote> +<p>设置/ 删除空闲钩子的接口如下:</p> +<pre><code>rt_err_t rt_thread_idle_sethook(void (*hook)(void)); +rt_err_t rt_thread_idle_delhook(void (*hook)(void)); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>设置/删除的钩子函数</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT-EOK</td> +<td>设置/删除成功</td> +</tr> +<tr> +<td>-RT_EFULL</td> +<td>设置失败</td> +</tr> +<tr> +<td>-RT_ENOSYS</td> +<td>删除失败</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。</code></p> +<h2 id="10设置调度器钩子">10.设置调度器钩子 +</h2><p><code>在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。</code></p> +<p>在系统线程切换时,这个钩子函数将被调用:</p> +<pre><code>void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); +</code></pre> +<p><code>设置调度器钩子函数的输入参数</code>如下表所示:</p> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>表示用户定义的钩子函数指针</td> +</tr> +</tbody> +</table> +<p><code>钩子函数hook() 的声明</code>如下:</p> +<pre><code>void hook(struct rt_thread* from, struct rt_thread* to); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>from</td> +<td>表示系统所要切换出的线程控制块指针</td> +</tr> +<tr> +<td>to</td> +<td>表示系统所要切换到的线程控制块指针</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。</code></p> +<hr> +<p>资料参考: +(1)<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5Ev7%5Earticle_score_rank,157%5Ev4%5Econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>【STM32】HAL库 STM32CubeMX教程五&mdash;-看门狗(独立看门狗,窗口看门狗)</a> +(2)<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>什么是钩子函数</a> +(3)<a class="link" href="https://www.rt-thread.org/document/site/#/" target="_blank" rel="noopener" +>RT-Thread文档中心</a></p>I2C(内核学习)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post I2C(内核学习)" /><h2 id="一i2c协议">一、i2c协议 +</h2><p>由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。</p> +<h2 id="二i2c物理层">二、i2c物理层 +</h2><ul> +<li> +<p>i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 +<code>SDA</code>:用于传输数据 +<code>SCL</code>:用于同步数据收发</p> +</li> +<li> +<p>每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问</p> +</li> +<li> +<p>i2c支持多主控,任何时间点都只能有一个主控。 +<img src="https://img-blog.csdnimg.cn/01cc1805f0db4842a836a7dae9b11978.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +</li> +<li> +<p>i2c器件的SDA引脚和SCL引脚是开漏电路<a class="link" href="https://blog.csdn.net/ngulb/article/details/81174233?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E5%BC%80%E6%BC%8F%E7%94%B5%E8%B7%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81174233.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>形式,因此,SDA和SCL总线都需要连接上拉电阻<a class="link" href="https://blog.csdn.net/fymx203/article/details/89426403?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164973690016782092947037%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164973690016782092947037&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-89426403.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E4%B8%8A%E6%8B%89%E7%94%B5%E9%98%BB&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>,当总线空闲时,两条总线均为高电平。</p> +</li> +<li> +<p>各器件的SDA和SCL信号线在总线上都是<code>线与</code>关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)</p> +</li> +</ul> +<h2 id="三i2c协议层">三、i2c协议层 +</h2><p>协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。</p> +<h4 id="1i2c总线的位传输">1.i2c总线的位传输 +</h4><p>数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 +数据改变:当SCL为低电平时,SDA才可以改变电平 +<code>i2c位传输时序图</code> +<img src="https://img-blog.csdnimg.cn/3bcc9522f82841b5a9808703e4c29fa9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2i2c总线的开始和结束信号">2.i2c总线的开始和结束信号 +</h4><p><code>开始信号</code>:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 +<code>结束信号</code>:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。</p> +<h4 id="3i2c应答信号">3.i2c应答信号 +</h4><ul> +<li>在<code>主机</code>发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答<code>ACK</code>(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)</li> +<li>当<code>从机</code>接收不到数据或通信故障时,<code>从机</code>必须使SDA保持高电平,<code>主机</code>产生一个结束信号终止传输或者产生新的传输。</li> +</ul> +<h4 id="4i2c总线的仲裁机制">4.i2c总线的仲裁机制 +</h4><ul> +<li>SDA的仲裁也是建立在总线具有<code>线与</code>逻辑功能的原理上的。</li> +<li>节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。</li> +<li>SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)</li> +<li>当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是<code>线与</code>连接。</li> +</ul> +<h2 id="四访问i2c总线设备">四、访问i2c总线设备 +</h2><p>一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:</p> +<table> +<thead> +<tr> +<th>函数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>rt_device_find()</td> +<td>根据I2C 总线设备名称查找设备获取设备<a class="link" href="https://blog.csdn.net/wyx0224/article/details/83385168?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164976053816780265492902%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164976053816780265492902&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-83385168.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E5%8F%A5%E6%9F%84&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>句柄</a></td> +</tr> +<tr> +<td>rt_i2c_transfer()</td> +<td>传输数据</td> +</tr> +</tbody> +</table> +<h2 id="五查找i2c总线设备">五、查找i2c总线设备 +</h2><p>在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,</p> +<pre><code>rt_device_t rt_device_find(const char* name); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td>i2c总线设备名称</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>&ndash;</td> +</tr> +<tr> +<td>设备句柄</td> +<td>查找到对应设备将返回相应的设备句柄</td> +</tr> +<tr> +<td>RT-NULL</td> +<td>没有找到相应的设备对象</td> +</tr> +</tbody> +</table> +<p>一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六数据传输">六、数据传输 +</h2><p>获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs[], +</span></span><span class="line"><span class="cl"> rt_uint32_t num); +</span></span></code></pre></td></tr></table> +</div> +</div><table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>bus</td> +<td>i2c总线设备句柄</td> +</tr> +<tr> +<td>msgs[]</td> +<td>待传输的消息数组指针</td> +</tr> +<tr> +<td>num</td> +<td>消息数组的元素个数</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>-</td> +</tr> +<tr> +<td>-</td> +<td>-</td> +</tr> +<tr> +<td>消息数组的元素个数</td> +<td>成功</td> +</tr> +<tr> +<td>错误码</td> +<td>失败</td> +</tr> +</tbody> +</table> +<ul> +<li>和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。</li> +<li>参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 +<code>!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。</code></li> +</ul> +<blockquote> +<p>I2C 消息数据结构原型如下:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct rt_i2c_msg +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">rt_uint16_t addr; /* 从机地址*/ +</span></span><span class="line"><span class="cl">rt_uint16_t flags; /* 读、写标志等*/ +</span></span><span class="line"><span class="cl">rt_uint16_t len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl">rt_uint8_t *buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。</li> +<li>标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 +<code>!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_I2C_WR 0x0000 /* 写标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_RD (1u &lt;&lt; 0) /* 读标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_ADDR_10BIT (1u &lt;&lt; 2) /* 10 位地址模式*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_START (1u &lt;&lt; 4) /* 无开始条件*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_IGNORE_NACK (1u &lt;&lt; 5) /* 忽视NACK */ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_READ_ACK (1u &lt;&lt; 6) /* 读的时候不发送ACK */ +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>使用示例如下所示:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">#define AHT10_ADDR 0x38 /* 从机地址*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 读传感器寄存器数据*/ +</span></span><span class="line"><span class="cl">static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t +</span></span><span class="line"><span class="cl">*buf) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs; +</span></span><span class="line"><span class="cl"> msgs.addr = AHT10_ADDR; /* 从机地址*/ +</span></span><span class="line"><span class="cl"> msgs.flags = RT_I2C_RD; /* 读标志*/ +</span></span><span class="line"><span class="cl"> msgs.buf = buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl"> msgs.len = len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl"> /* 调用I2C设备接口传输数据*/ +</span></span><span class="line"><span class="cl"> if (rt_i2c_transfer(bus, &amp;msgs, 1) == 1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return RT_EOK; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return -RT_ERROR; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七i2c-总线设备使用示例">七、I2C 总线设备使用示例 +</h2><p>I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:</p> +<ol> +<li>首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。</li> +<li>控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() +这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">/*</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序清单:</span> <span class="err">这是一个</span><span class="n">I2C</span> <span class="err">设备使用例程</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">例程导出了</span><span class="n">i2c_aht10_sample</span> <span class="err">命令到控制终端</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令调用格式:</span> <span class="n">i2c_aht10_sample</span> <span class="n">i2c1</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令解释:</span> <span class="err">命令第二个参数是要使用的</span><span class="n">I2C总线设备名称</span><span class="err">,</span> <span class="err">为空则使用默认的</span><span class="n">I2C总线设备</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序功能:</span> <span class="err">通过</span><span class="n">I2C</span> <span class="err">设备读取温湿度传感器</span><span class="n">aht10</span> <span class="err">的温湿度数据并打印</span> +</span></span><span class="line"><span class="cl"><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtdevice.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_ADDR 0x38 /* 从机地址*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_GET_DATA 0xAC /* 获取数据命令*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">i2c_bus</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> <span class="o">/*</span> <span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_bool_t</span> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_FALSE</span><span class="p">;</span> <span class="o">/*</span> <span class="err">传感器初始化状态</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">写传感器寄存器</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">write_reg</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">reg</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">reg</span><span class="p">;</span> <span class="o">//</span><span class="n">cmd</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_WR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">读传感器寄存器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">read_regs</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">len</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">buf</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_RD</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">read_temp_humi</span><span class="p">(</span><span class="ne">float</span> <span class="o">*</span><span class="n">cur_temp</span><span class="p">,</span> <span class="ne">float</span> <span class="o">*</span><span class="n">cur_humi</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_GET_DATA</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">/*</span> <span class="err">发送命令</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_regs</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> <span class="o">/*</span> <span class="err">获取传感器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">湿度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_humi</span> <span class="o">=</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">12</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span> <span class="o">|</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf0</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">*</span> <span class="mf">100.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span><span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">温度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_temp</span> <span class="o">=</span> <span class="p">((</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="o">*</span> <span class="mf">200.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">)</span><span class="o">-</span> <span class="mi">50</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">aht10_init</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">查找</span><span class="n">I2C总线设备</span><span class="err">,</span> <span class="err">获取</span><span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">i2c_bus</span> <span class="o">=</span> <span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="p">)</span><span class="n">rt_device_find</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i2c_bus</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;can&#39;t find </span><span class="si">%s</span><span class="s2"> device!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_NORMAL_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x08</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_CALIBRATION_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_TRUE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">i2c_aht10_sample</span><span class="p">(</span><span class="ne">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">char</span> <span class="n">name</span><span class="p">[</span><span class="n">RT_NAME_MAX</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">AHT10_I2C_BUS_NAME</span><span class="p">,</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">传感器初始化</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">aht10_init</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">读取温湿度数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_temp_humi</span><span class="p">(</span><span class="o">&amp;</span><span class="n">temperature</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor humidity : </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2"> </span><span class="si">%%</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span> <span class="n">temperature</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="o">-</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;initialize sensor failed!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">导出到</span><span class="n">msh</span> <span class="err">命令列表中</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">i2c_aht10_sample</span><span class="p">,</span> <span class="n">i2c</span> <span class="n">aht10</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>学习资料参考:<a class="link" href="https://item.jd.com/10022312146340.html" target="_blank" rel="noopener" +>《嵌入式系统设计》</a>、<a class="link" href="https://club.rt-thread.org/index.html" target="_blank" rel="noopener" +>RT-Thread</a></p>RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/cover.jpg" alt="Featured image of post RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)" /><h2 id="一初识rt-thread">一、初识RT-Thread +</h2><p><code>做世界级的 OS,让万物互联,信息畅通无阻。</code> +<code>成为未来 AIoT 领域最为主流的操作系统平台。</code></p> +<h4 id="1简介">1.简介 +</h4><blockquote> +<p>RT-Thread 是一个集<code>实时操作系统(RTOS)内核、中间件组件和开发者社区于一体</code>的技术平台,由<code>熊谱翔先生</code>带领并集合开源社区力量开发而成,RT-Thread 也是一个<code>组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性</code>的<code>物联网操作系统</code>。</p> +</blockquote> +<h4 id="2前景">2.前景 +</h4><blockquote> +<p>RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个<code>国内最大的嵌入式开源社区</code>,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人<code>自主开发</code>、国内最成熟稳定和装机量最大的<code>开源 RTOS</code>。</p> +</blockquote> +<h4 id="3软件生态">3.软件生态 +</h4><blockquote> +<p>RT-Thread 拥有<code>良好的软件生态</code>,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。</p> +</blockquote> +<h2 id="二实验准备">二、实验准备 +</h2><ul> +<li>编程工具:<code>RT-Thread studio</code></li> +<li>开发板:<code>潘多拉STM32L475</code></li> +</ul> +<hr> +<h2 id="三实验需求">三、实验需求 +</h2><ul> +<li>1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 +右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。</li> +<li>2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。</li> +</ul> +<h2 id="四操作流程">四、操作流程 +</h2><h4 id="1新建rt-thread工程">1.新建RT-Thread工程 +</h4><p><img src="https://img-blog.csdnimg.cn/85370c1057554323ba75dd83c3d1844f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rt-thread-studio界面介绍">2.RT-Thread Studio界面介绍 +</h4><p><img src="https://img-blog.csdnimg.cn/b24064da660f40b5b00e9e0f03d4f1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="3代码编写">3.代码编写 +</h4><p><img src="https://img-blog.csdnimg.cn/c556436b0d44443686dafa3a0f389bd5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="4烧录">4.烧录 +</h4><p><img src="https://img-blog.csdnimg.cn/c5ea1524e61e4b92af667e17decd12bb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5串口监视">5.串口监视 +</h4><p><img src="https://img-blog.csdnimg.cn/eae3d5a76ae14aa0a7e6a2d00145024d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="五代码演示">五、代码演示 +</h2><p><code>1.头文件</code></p> +<pre><code>#include &lt;rtthread.h&gt; +#include &lt;rtdevice.h&gt; +#include &lt;board.h&gt; +</code></pre> +<p><code>2.宏定义</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">//</span><span class="err">按键初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">电机初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">蜂鸣器初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_BEEP GET_PIN(B,2)//PB2:BEEP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">enum</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_STOP</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_LEFT</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_RIGHT</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>3.void motor_ctrl(rt_uint8_t turn) //电机控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void motor_ctrl(rt_uint8_t turn) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (turn == MOTOR_STOP) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_LEFT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_RIGHT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_HIGH); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;err parameter ! Please enter 0-2.&#34;); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void beep_ctrl(rt_uint8_t on) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (on) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.void irq_callback(void *args) // 中断回调函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void irq_callback(void *args) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> rt_uint32_t sign = (rt_uint32_t)args; +</span></span><span class="line"><span class="cl"> switch (sign) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> case PIN_KEY0: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_LEFT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY0 interrupt. motor turn left.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY1: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_RIGHT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY1 interrupt. motor turn right.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY2: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_STOP); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY2 interrupt. motor stop.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> default: +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;error sign= %d !&#34;, sign); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> unsigned int count = 1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置电机控制引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置蜂鸣器引脚为输出模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键中断模式与中断回调函数*/ +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 使能中断*/ +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> while (count &gt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(50); +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;WK_UP pressed. beep on.&#34;); +</span></span><span class="line"><span class="cl"> beep_ctrl(1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> beep_ctrl(0); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(10); +</span></span><span class="line"><span class="cl"> count++; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六原理讲解">六、原理讲解 +</h2><p><!-- raw HTML omitted -->通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 +1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 +2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。<!-- raw HTML omitted --></p> +<table> +<thead> +<tr> +<th>按键</th> +<th>功能</th> +</tr> +</thead> +<tbody> +<tr> +<td>KEY0</td> +<td>电机左转</td> +</tr> +<tr> +<td>KEY1</td> +<td>电机右转</td> +</tr> +<tr> +<td>KEY2</td> +<td>电机停止</td> +</tr> +<tr> +<td>WK_UP</td> +<td>蜂鸣器响</td> +</tr> +</tbody> +</table>RT-Thread Studio使用 2.内核实战篇(线程)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/cover.jpg" alt="Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)" /><p>详细原理参考:<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<h2 id="一线程创建">一、线程创建 +</h2><h4 id="1函数原型">1、函数原型 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 线程创建 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_thread_t</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>首先我们来看看线程创建函数返回值类型:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/de83fe0a4aad4ffe9989eacdf86e96df.png" +loading="lazy" +></p> +<blockquote> +<p>可以看到线程创建函数的返回值类型为:<code>rt_thread_t</code>,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1dfc5d7964484cae9cc44d8067ffcdd0.png" +loading="lazy" +></p> +<h4 id="2线程定义">2、线程定义 +</h4><p>那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1_ptr</span> <span class="o">=</span> <span class="nb">NULL</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>接下来就是我们给进程控制块传参了</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/90d481586b964d01958c9a14a2bd4695.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/7f39dba639bb4c5faeed06524f57a60d.png" +loading="lazy" +></p> +<h4 id="3线程创建判断">3、线程创建判断 +</h4><p>由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功</p> +<p>我们先来看下线程返回值(如下图)</p> +<blockquote> +<p>如果<code>成功创建</code>的话,返回值是会返回我们所创建的线程对象的</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b19a07990b2240728d423f2c7064d47c.png" +loading="lazy" +></p> +<blockquote> +<p>如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/faf3ad30a6f046638db1c77a0c8275a4.png" +loading="lazy" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span><span class="p">(</span><span class="n">th1_ptr</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//错误信息打印 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_thread_create create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> <span class="c1">// 设定当线程th1_ptr创建失败后,返回一个空间不足的标志 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">//打印debug调试信息 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_thread_create create successed ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4线程入口函数">4、线程入口函数 +</h4><p>我们在线程的入口处理函数写一个循环函数:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源</code></p> +<ul> +<li>编译,串口观察</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4c5556830c644e48bfa76008218fb680.png" +loading="lazy" +></p> +<p>由于RTT studio有内置的串口终端,我们直接打开</p> +<p><img src="https://img-blog.csdnimg.cn/cd4fd4b573c0421a88a73d9f8e7160dd.png" +loading="lazy" +></p> +<p>终端输入list_thread可以查看所有的线程</p> +<p><img src="https://img-blog.csdnimg.cn/edae1f6480c54759915145477406f17d.png" +loading="lazy" +></p> +<h4 id="5总结">5、总结 +</h4><p>这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?</p> +<p>其实我们再看th_demo线程的状态可以看到是<code>init</code>,参考<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<p><code>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</code></p> +<p>其实这句话就表明当<code>线程处于初始化状态下是不参与系统调度</code>的!</p> +<h4 id="6补充">6、补充 +</h4><p>线程错误码:</p> +<p><img src="https://img-blog.csdnimg.cn/f32f5440cb604b2d8eea4a4546d977b0.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<h2 id="二线程启动">二、线程启动 +</h2><p>函数原型</p> +<p>在主函数中加入命令,使线程进入就绪态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_thread_startup(th1_ptr); +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为<code>挂起态</code></p> +<p><img src="https://img-blog.csdnimg.cn/f5f40f386046488f89e56ab8ee8db6d4.png" +loading="lazy" +></p> +<p><code>解释:</code>虽然我们调用<code>rt_thread_startup</code>函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了<code>rt_thread_mdelay</code>函数使其有一定时间的休眠,从而进入了挂起态`</p> +<h2 id="三初始化线程">三、初始化线程 +</h2><p><code>rt_thread_init</code></p> +<h4 id="1函数声明">1、函数声明 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 模板函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_err_t</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="k">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="kr">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2函数定义">2、函数定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th2</span><span class="p">,</span><span class="s">&#34;th2_demo&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">th2_stack</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">th2_stack</span><span class="p">),</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>此处我们需要定义一个ret整型变量用于<code>rt_thread_init</code>的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b7ce209e742948a398d235d4fd799279.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/06a57b94d88c4cdf97f9a431d1578862.png" +loading="lazy" +></p> +<h4 id="3线程入口函数">3、线程入口函数 +</h4><p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">10</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4判断创建状态">4、判断创建状态 +</h4><p>静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用<code>rt_thread_startup</code>函数使线程2进入就绪态,并执行线程处理函数。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">if(ret &lt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> LOG_E(&#34;rt2_thread_create create failed ...\n&#34;); // 错误信息打印 +</span></span><span class="line"><span class="cl"> return ret; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> LOG_D(&#34;rt_thread2_create create successes ...\n&#34;); +</span></span><span class="line"><span class="cl"> rt_thread_startup(&amp;th2); // 创建成功后,我们开启线程,使其进入就绪态 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启</p> +</blockquote> +<h4 id="5实验结果">5、实验结果 +</h4><blockquote> +<p>分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/861754f210a74896a6d63d20fbb629f0.png" +loading="lazy" +></p> +<blockquote> +<p>线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/85333e4d1b1942d6a59b10e528797ecc.png" +loading="lazy" +></p>ubuntu安装交叉编译工具链https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/cover.jpg" alt="Featured image of post ubuntu安装交叉编译工具链" /><h1 id="ubuntu安装交叉编译工具链附避坑指南">ubuntu安装交叉编译工具链(附避坑指南) +</h1><blockquote> +<p>1.打开Ubuntu,在终端进入/usr/local/目录下</p> +</blockquote> +<pre><code>cd /usr/local/ +</code></pre> +<blockquote> +<p>2.在local/目录下创建一个名为arm的文件夹</p> +</blockquote> +<pre><code>mkdir arm +</code></pre> +<blockquote> +<p>3.在自己的共享文件夹下找到<a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a>,并复制到之前创建的arm目录下</p> +</blockquote> +<pre><code>cp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/ +</code></pre> +<blockquote> +<p>4.进入到arm目录下,解压该其中文件</p> +</blockquote> +<pre><code>cd /usr/local/arm +tar -jxvf arm-2009q3.tar.bz2 +</code></pre> +<blockquote> +<p>5.然后执行:</p> +</blockquote> +<pre><code>cd arm-2009q3/bin +./arm-none-linux-gnueabi-gcc -v +</code></pre> +<p><code>注意:</code><!-- raw HTML omitted -->这里如果输入<code>./arm-none-linux-gnueabi-gcc -v</code>终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持</p> +<pre><code>sudo apt-get install libc6:i386 +</code></pre> +<p><!-- raw HTML omitted -->安装好了之后重新输入<code>./arm-none-linux-gnueabi-gcc -v</code> +<img src="https://img-blog.csdnimg.cn/b0660902aed64a88a257ed92b892b8f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<!-- raw HTML omitted -->操作成功!</p> +<blockquote> +<p>6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 +打开配置文件</p> +</blockquote> +<pre><code>sudo vim /etc/profile +</code></pre> +<blockquote> +<p>7.在vi界面末尾处加入</p> +</blockquote> +<pre><code>export PATH=$PATH:/usr/local/arm/arm-2009q3/bin +</code></pre> +<blockquote> +<p>8.回到主目录,查看交叉编译工具是否可用</p> +</blockquote> +<pre><code>cd ~ +source /etc/profile +</code></pre> +<p><code>注</code> <!-- raw HTML omitted -->这里如果没有出现相关信息,切换root用户再次输入命令</p> +<p>使用 <code>echo $PATH</code>查看交叉编译链的安装路径是否加入了环境变量。 +使用<code>arm-linux-gnueabihf-gcc -v</code>测试交叉编译链是否好使</p> +<blockquote> +<p>9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:</p> +</blockquote> +<pre><code>chmod 777 mk-arm-linux-.sh +./mk-arm-linux-.sh +</code></pre> +<p><code>这里由于运行时报错,原因详见</code><a class="link" href="https://blog.csdn.net/LWJdear/article/details/79868551?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=bash:%20./mk-arm-linux-.sh:%20Perm&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-79868551.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>解决linux的-bash: ./xx.sh: Permission denied</a></p> +<blockquote> +<p>ls查看,可以发现符号链接出现,到此,交叉编译链配置成功!</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/6dc86a581621467d8639643cc154877a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p><code>附件</code>:</p> +<ul> +<li> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a></p> +</li> +<li> +<p><code>mk-arm-linux-.sh脚本文件</code></p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ar -s arm-linux-ar +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-as -s arm-linux-as +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++ -s arm-linux-c++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-g++ -s arm-linux-g++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1 +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ld -s arm-linux-ld +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-nm -s arm-linux-nm +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-size -s arm-linux-size +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strings -s arm-linux-strings +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strip -s arm-linux-strip +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<p><code>有问题欢迎评论留言致信:</code><a class="link" href="https://blog.csdn.net/qq_56914146?type=blog" target="_blank" rel="noopener" +>blogs</a></p>ubuntu桌面恢复(20.04)https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/<img src="https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/cover.jpg" alt="Featured image of post ubuntu桌面恢复(20.04)" /><h3 id="恢复ubuntu2004默认桌面管理器">恢复ubuntu20.04默认桌面管理器 +</h3><ul> +<li> +<ul> +<li> +<ul> +<li><a class="link" href="#GDM_KDM_LightDM_SDDM_5" >一、GDM, KDM, LightDM, SDDM的区别和安装配置</a></li> +<li> +<ul> +<li><a class="link" href="#1GDMgnome_8" >1、GDM,gnome系列的图形管理器</a></li> +<li><a class="link" href="#2KDMSDDMKDE_17" >2、KDM,SDDM是KDE系列的图形管理器</a></li> +<li><a class="link" href="#3LightDM_27" >3、LightDM</a></li> +</ul> +</li> +<li><a class="link" href="#_37" >二、配置和切换</a></li> +<li><a class="link" href="#ubuntu2004_62" >三、恢复ubuntu20.04默认桌面管理器</a></li> +<li> +<ul> +<li><a class="link" href="#1_65" >1、打开终端,用管理员口令下载相关资源</a></li> +<li><a class="link" href="#2gnomeshell_71" >2、安装gnome-shell</a></li> +<li><a class="link" href="#3ubuntugnomedesktop_80" >3、安装ubuntu-gnome-desktop</a></li> +<li><a class="link" href="#4unitytweaktoolgnometweaktool_85" >4、安装unity-tweak-tool和gnome-tweak-tool</a></li> +<li><a class="link" href="#5_94" >5、安装完成后重启</a></li> +</ul> +</li> +</ul> +</li> +</ul> +</li> +</ul> +<p>起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能<a class="link" href="https://blog.csdn.net/irober/article/details/112608610" target="_blank" rel="noopener" +>远程控制桌面</a>了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(<strong>gnome图形管理器</strong>)也变成了我不喜欢的风格(<strong>轻量级的LightDM</strong>)了,大家以后要慎重。<br> +注意:我是个半吊子,仅供参考。</p> +<h3 id="一gdm-kdm-lightdm-sddm的区别和安装配置">一、GDM, KDM, LightDM, SDDM的区别和安装配置 +</h3><p><a class="link" href="https://blog.csdn.net/u014466109/article/details/105572470" target="_blank" rel="noopener" +>GDM, KDM, LightDM, SDDM的区别和安装配置</a><br> +<strong>gdm3,kdm 和 lightdm</strong> 都是显示管理器。 它们提供图形化登录并处理用户身份验证。</p> +<h4 id="1gdmgnome系列的图形管理器">1、GDM,gnome系列的图形管理器 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2kdmsddm是kde系列的图形管理器">2、KDM,SDDM是KDE系列的图形管理器 +</h4><p>kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3lightdm">3、LightDM +</h4><p>LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="二配置和切换">二、配置和切换 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。</p> +<p>要检查当前正在使用的显示管理器,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cat</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">X11</span><span class="o">/</span><span class="n">default</span><span class="o">-</span><span class="n">display</span><span class="o">-</span><span class="n">manager</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。</p> +<h3 id="三恢复ubuntu2004默认桌面管理器">三、恢复ubuntu20.04默认桌面管理器 +</h3><p><a class="link" href="https://www.zhihu.com/tardis/sogou/art/27659651" target="_blank" rel="noopener" +>恢复ubuntu20.04默认桌面管理器</a><br> +目前Ubuntu的主流桌面<strong>GNOME</strong>, Ubntu的内置桌面是<strong>Untiy</strong></p> +<h4 id="1打开终端用管理员口令下载相关资源">1、打开终端,用管理员口令下载相关资源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">Ctrl</span><span class="o">+</span><span class="n">Alt</span><span class="o">+</span><span class="n">T</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开终端,用管理员口令下载相关资源</p> +<h4 id="2安装gnome-shell">2、安装gnome-shell +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">shell</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<p>管理员权限需要输入密码,但是系统不会显示你输入的密码<br> +输入完成后,直接回车即可</p> +<h4 id="3安装ubuntu-gnome-desktop">3、安装ubuntu-gnome-desktop +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">ubuntu</span><span class="o">-</span><span class="n">gnome</span><span class="o">-</span><span class="n">desktop</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装unity-tweak-tool和gnome-tweak-tool">4、安装unity-tweak-tool和gnome-tweak-tool +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">unity</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5安装完成后重启">5、安装完成后重启 +</h4><p>然后一切恢复如初,仿佛没发生过。</p>x11vnc安装与配置https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/<img src="https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/cover.jpg" alt="Featured image of post x11vnc安装与配置" /><h1 id="1-安装x11vnc">1. 安装x11vnc +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install x11vnc -y +</span></span></code></pre></td></tr></table> +</div> +</div><p>直接安装成功。</p> +<h1 id="2-设置vnc密码">2. 设置vnc密码 +</h1><p>密码存储在/etc/目录里面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo x11vnc -storepasswd /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><p>放在这个位置,需要设置文件读取权限<br> +否则会提示密码校验失败</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><h1 id="3创建vnc配置文件">3.创建vnc配置文件 +</h1><p>在/etc/init 下创建一个x11vnc.conf的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> <span class="nb">cd</span> /etc/init +</span></span><span class="line"><span class="cl"> sudo gedit x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>文件内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#description &#34;xiaoqiang vnc server&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#start on runlevel [2345]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#stop on runlevel [06]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#script</span> +</span></span><span class="line"><span class="cl"> <span class="nb">exec</span> /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport <span class="m">5900</span> -shared +</span></span><span class="line"><span class="cl"><span class="c1">#end script</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。</p> +<h1 id="4启动vnc服务">4.启动vnc服务 +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/12b8d37ebfbb4160a7d50196cf3bd2b7.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了</p> +<h1 id="5设置自启动">5.设置自启动 +</h1><p>我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。</p> +<h2 id="1首先编写一个脚本">(1)首先编写一个脚本 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gedit x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>添加以下内容<br> +第一行是要添加的解释器,后面是要执行的指令内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>防止误删,从home移动到/etc/init.d/文件夹中<br> +并添加权限</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mv x11vnc.sh /etc/init.d/ +</span></span><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2添加启动项">(2)添加启动项 +</h2><p>点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。<br> +<img src="https://img-blog.csdnimg.cn/b1f7234307b64d9ca6844704a100a243.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +点击右侧添加,添加自动启动项。<br> +<img src="https://img-blog.csdnimg.cn/fd2f7303980f4e7598e7f4ce6950ef20.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +添加内容如下;重要的是第二行,</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bash /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>用bash启动才能成功,保存之后重启,确实可以开机自启了。<br> +<img src="https://img-blog.csdnimg.cn/caa1005977844d8baffbba60e7d6ea93.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="6x11vnc配置安装虚拟显卡驱动">6.x11vnc配置(安装虚拟显卡驱动) +</h1><p>如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示</p> +<h2 id="1首先还是安装命令">(1)首先还是安装命令 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install xserver-xorg-video-dummy +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2接下来就是创建配置文件-etcx11xorgconf">(2)接下来就是创建配置文件 <code>/etc/X11/xorg.conf</code> +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Section &#34;Device&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> Driver &#34;dummy&#34; +</span></span><span class="line"><span class="cl"> VideoRam 64000 +</span></span><span class="line"><span class="cl"> Option &#34;IgnoreEDID&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl"> Option &#34;NoDDC&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> HorizSync 15.0-100.0 +</span></span><span class="line"><span class="cl"> VertRefresh 15.0-200.0 +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Monitor &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Device &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> DefaultDepth 24 +</span></span><span class="line"><span class="cl"> SubSection &#34;Display&#34; +</span></span><span class="line"><span class="cl"> Depth 24 +</span></span><span class="line"><span class="cl"> Modes &#34;1280x720&#34; +</span></span><span class="line"><span class="cl"> EndSubSection +</span></span><span class="line"><span class="cl">EndSection +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3再修改个文件加点配置">(3)再修改个文件加点配置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /boot/firmware/usercfg.txt +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">framebuffer_width=1280 +</span></span><span class="line"><span class="cl">framebuffer_height=720 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>如果想要恢复显示器的连接,可以先使用ssh访问终端并将<code>/etc/X11/xorg.conf</code>这个文件删除,再次重启即可</strong></p>时钟管理(原理+实战)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/Wed, 13 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/cover.jpg" alt="Featured image of post 时钟管理(原理+实战)" /><h2 id="一时钟节拍">一、时钟节拍 +</h2><p>任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。</p> +<p>RT-Thread 中,时钟节拍的长度可以根据 <code>RT_TICK_PER_SECOND</code> 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,<code>系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!</code></p> +<p>rtconfig.h配置文件中定义:</p> +<blockquote> +<ul> +<li> +<p>频率是1000HZ周期是1/1000 s</p> +</li> +<li> +<p>所以节拍是1ms</p> +</li> +<li> +<p>#define RT_ <em>TiCK</em> PER_ SECOND 1000</p> +</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d00c117cba6245909ad5fdab19c9bf74.png" +loading="lazy" +></p> +<h4 id="1void-systick_handler">1、void SysTick_Handler() +</h4><p>在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行<code>void SysTick_Handler</code>(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)</p> +<p><img src="https://img-blog.csdnimg.cn/c97f508be8c844a7bfa08cff57233dc1.png" +loading="lazy" +></p> +<blockquote> +<p>可以发现在<code>void SysTick_Handler()</code>这个函数中,首先会执行中断入口函数,然后<code>void rt_tick_increase</code>对<code>rt_tick</code>(系统滴答时钟,初值为0,静态<code>全局变量</code>)进行自加操作,会记录从启动到现在的时钟节拍数</p> +</blockquote> +<h4 id="2void-rt_tick_increase">2、void rt_tick_increase() +</h4><p><img src="https://img-blog.csdnimg.cn/b7122a14e60444e29f36e106bfb5166d.png" +loading="lazy" +></p> +<p><code>也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断 </code></p> +<h4 id="3rt_tick_getvoid">3、rt_tick_get(void); +</h4><p>名称:获取系统统计函数</p> +<p>功能:返回当前操作系统的时钟数</p> +<p>返回值:返回当前时钟数</p> +<p><img src="https://img-blog.csdnimg.cn/dd9e18ad7b4942ce9af13f1870fcc232.png" +loading="lazy" +></p> +<h2 id="二定时器管理">二、定时器管理 +</h2><h4 id="1概念">1、概念 +</h4><p>定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有<code>硬件定时器</code>和<code>软件定时器</code>之分:</p> +<p>1)<strong>硬件定时器</strong>是芯片本身提供的定时功能。<code>一般是由外部晶振(HSE)提供给芯片输入时钟</code>,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是<code>中断触发方式</code>。</p> +<p>2)<strong>软件定时器</strong>是由<code>操作系统提供的一类系统接口</code>,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。</p> +<p>RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即<code>定时数值必须是 OS Tick 的整数倍</code>,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。</p> +<h4 id="2rt-thread定时器介绍">2、RT-Thread定时器介绍 +</h4><p>RT-Thread 的定时器提供两类定时器机制:</p> +<p>第一类是<code>单次触发</code>定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 +第二类是<code>周期触发</code>定时器,这类定时器会周期性的触发定时器事件,直到<code>用户手动的停止</code>,否则将永远持续执行下去。</p> +<p>另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 <code>HARD_TIMER </code>模式(硬件定时器模式)与<code> SOFT_TIMER</code> 模式(软件定时器模式),如下图。</p> +<p><img src="https://img-blog.csdnimg.cn/36887975b53c4dc684343c70a2f8db09.png" +loading="lazy" +></p> +<p>1)HARD_TIMER 模式:中断上下文</p> +<p>HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数<code>RT_TIMER_FLAG_HARD_TIMER</code>来指定。</p> +<p>在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:<code>执行时间应该尽量短,执行时不应导致当前上下文挂起、等待</code>。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。</p> +<p>2)SOFT_TIMER 模式:线程上下文</p> +<p>SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。</p> +<p>该模式被启用后,系统会在<code>初始化时创建一个 timer 线程</code>,然后 <code>SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行</code>。可以在初始化 / 创建定时器时使用参数 <code>RT_TIMER_FLAG_SOFT_TIMER </code>来指定设置 <code>SOFT_TIMER</code> 模式。</p> +<h4 id="3定时器源码分析">3、定时器源码分析 +</h4><p>1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/0ee79523a62540a7a18155a0d9010365.png" +loading="lazy" +></p> +<p>2)rt_system_timer_init(硬件定时器初始化)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_system_timer_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span><span class="c1">// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_list_init</span><span class="p">(</span><span class="n">rt_timer_list</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)rt_system_timer_thread_init(软件定时器初始化)</p> +<p><img src="https://img-blog.csdnimg.cn/68e5d39a7cf94149a474f05b0f370717.png" +loading="lazy" +></p> +<h4 id="4定时器工作机制">4、定时器工作机制 +</h4><p>下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的<code>全局变量</code>:</p> +<p>(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);</p> +<p>(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照<code>以超时时间排序</code>的方式<code>插入到 rt_timer_list 链表</code>中。</p> +<p>如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。</p> +<p><img src="https://img-blog.csdnimg.cn/bb6521cccf884694867fd32a5c76da27.png" +loading="lazy" +></p> +<p>而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),<code>50 个 tick 以后,rt_tick 从 20 增长到 70</code>,与 <code>Timer1 的 timeout 值相等</code>,这时会<code>触发与 Timer1 定时器相关联的超时函数</code>,同时将 <code>Timer1 从 rt_timer_list 链表上删除</code>。</p> +<p>同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。</p> +<p>如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 <code>timeout=rt_tick+300=330</code>, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:</p> +<p><img src="https://img-blog.csdnimg.cn/515005f47d5148848a7ea4fe883b6f39.png" +loading="lazy" +></p> +<h4 id="5定时器相关接口">5、定时器相关接口 +</h4><p>1)<strong>动态创建定时器</strong></p> +<p>动态创建声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>详细函数定义:</p> +<p><img src="https://img-blog.csdnimg.cn/87411b4f65564541a22792b8fc676ec1.png" +loading="lazy" +></p> +<p>查看flag定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_ONE_SHOT 0x0 </span><span class="c1">// 单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_PERIODIC 0x2 </span><span class="c1">// 周期性触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_HARD_TIMER 0x0 </span><span class="c1">// 硬件定时器模式 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_SOFT_TIMER 0x4 </span><span class="c1">// 软件定时器模式 +</span></span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>同时这里我们注意到<code>rt_timer_create</code>这个函数的返回值是<code>rt_timer_t</code>,通过查找定义可以发现该类型是通过typedef重命名的</p> +<p>也就是说<code>struct rt_timer</code> &lt;=&gt;<code>*rt_timer_t</code></p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">rt_timer</span> <span class="o">*</span><span class="kt">rt_timer_t</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; inherit from rt_object */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_list_t</span> <span class="n">row</span><span class="p">[</span><span class="n">RT_TIMER_SKIP_LIST_LEVEL</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout_func</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">);</span> <span class="cm">/**&lt; timeout function */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">;</span> <span class="cm">/**&lt; timeout function&#39;s parameter */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">init_tick</span><span class="p">;</span> <span class="cm">/**&lt; timer timeout tick */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout_tick</span><span class="p">;</span> <span class="cm">/**&lt; timeout tick */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2)<strong>删除定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_timer_delete(rt_timer_t timer); +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:返回操作系统的状态,成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/71ccf0b21d70422fa817b7f9ae7d6843.png" +loading="lazy" +></p> +<p>3)<strong>动态创建定时器演示</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义 )。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写中断回调函数(超时函数) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 返回值结构图定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>4)<strong>开启定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/3542f82f0cc84f4f9c74b871c17753fe.png" +loading="lazy" +></p> +<p>5)实例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在超时函数中编写代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息</p> +<p>6)<strong>静态创建定时器</strong></p> +<p>函数定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们看下<code>rt_timer_init</code>这个函数的返回值和参数</p> +<p>返回值:void</p> +<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">timer</td> +<td style="text-align:center">结构体指针类型</td> +</tr> +<tr> +<td style="text-align:center">name</td> +<td style="text-align:center">名字</td> +</tr> +<tr> +<td style="text-align:center">timeout</td> +<td style="text-align:center">超时回调函数指针</td> +</tr> +<tr> +<td style="text-align:center">parameter</td> +<td style="text-align:center">传递给超时回调函数的参数</td> +</tr> +<tr> +<td style="text-align:center">time</td> +<td style="text-align:center">定时器时间</td> +</tr> +<tr> +<td style="text-align:center">flag</td> +<td style="text-align:center">定时器标志</td> +</tr> +</tbody> +</table> +<p>7)<strong>脱离函数</strong>(静态创建时使用)</p> +<p>描述:当<code>静态创建</code>的定时器不需要在使用时,我们调用下面这个函数接口</p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_detach</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>返回值:成功返回0,失败返回1</p> +<p>8)<strong>定时器控制</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> <span class="kt">int</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>cmd命令定义查看</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_TIME 0x0 </span><span class="cm">/**&lt; set timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_TIME 0x1 </span><span class="cm">/**&lt; get timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_ONESHOT 0x2 </span><span class="cm">/**&lt; change timer to one shot */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_PERIODIC 0x3 </span><span class="cm">/**&lt; change timer to periodic */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_STATE 0x4 </span><span class="cm">/**&lt; get timer run state active or deactive*/</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cb30a12c60e24f51a5ef081c296347bd.png" +loading="lazy" +></p> +<p>实例:</p> +<blockquote> +<p>查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/67007c956ebd48478e44b9233abd8efe.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> <span class="n">tm2</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm2_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">10</span><span class="p">)</span><span class="c1">// 当flags标志位位10时,设置单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_ONESHOT</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_TIME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">timeout</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[%u]tm2_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="nf">rt_tick_get</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 动态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 静态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span><span class="s">&#34;tm2_demo&#34;</span><span class="p">,</span><span class="n">tm2_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="三高精度延时">三、高精度延时 +</h2><blockquote> +<p><code>注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间</code></p> +</blockquote> +<ul> +<li>函数声明:<code>void rt_hw_us_delay(rt_uint32_t us);</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/43a92b7bdd884f18bf6ce522214cb520.png" +loading="lazy" +></p> +<ul> +<li>应用场景:应用于某些场景下对高精度延时有要求的情况下</li> +</ul>env工具学习https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post env工具学习" /><h4 id="一基础配置">一、基础配置 +</h4><p>1.首先需要下载git并配置好相应的环境变量</p> +<p>2.双击env,在setting中设置</p> +<p><img src="https://img-blog.csdnimg.cn/709a490d50c24945a2b06409d51b3209.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这样就可以指定文件夹打开env工具了</p> +<h4 id="二基本命令学习">二、基本命令学习 +</h4><p>1.scons:编译</p> +<p><img src="https://img-blog.csdnimg.cn/976aba29a258481d9128f4b984f78139.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]" +></p> +<p><code>(1)scons:</code>编译并打印相关内部信息 +<code>(2)scons -c:</code>清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +<code>(3)scons -s:</code>编译而不打印具体的内部命令 +<code>(4)scons --target=XXX:</code>使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=iar +</span></span><span class="line"><span class="cl">scons --target=mdk4 +</span></span><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(5)scons -jN:</code>多线程编译目标,在多核计算机上可以使用此命令加快编译速度</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons -j4 //双核编译工程 +</span></span></code></pre></td></tr></table> +</div> +</div><p><!-- raw HTML omitted -->注意:一般不建议使用,容易将编译信息和错误混杂<!-- raw HTML omitted --> +<code>(6)scons --dist:</code>搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set RTT_CC=keil +</span></span><span class="line"><span class="cl">set RTT_EXEC_PATH=C:/Keilv5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.menuconfig +打开菜单配置界面,可用户自定义模块</p> +<p>4.scons进阶学习 +scons内置函数</p> +<ul> +<li> +<p>GetCurrentDir(): +获取当前路径。</p> +</li> +<li> +<p>Glob(&rsquo;*.c&rsquo;): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。</p> +</li> +<li> +<p>GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。</p> +</li> +<li> +<p>Split(str): +将字符串 str 分割成一个列表 list。</p> +</li> +<li> +<p>DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +<code>DefineGroup()</code> 函数的参数描述:</p> +</li> +</ul> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th style="text-align:center"><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td style="text-align:center">Group 的名字</td> +</tr> +<tr> +<td>src</td> +<td style="text-align:center">Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件</td> +</tr> +<tr> +<td>depend</td> +<td style="text-align:center">Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现</td> +</tr> +<tr> +<td>parameters</td> +<td style="text-align:center">配置其他参数,可取值见下表,实际使用时不需要配置所有参数</td> +</tr> +</tbody> +</table> +<p>parameters可加入的参数:</p> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>dirs</td> +<td>SConscript 文件路径</td> +</tr> +<tr> +<td>variant_dir</td> +<td>指定生成的目标文件的存放路径</td> +</tr> +<tr> +<td>duiplicate</td> +<td>设定是否拷贝或链接源文件到 variant_dir</td> +</tr> +</tbody> +</table>Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/Tue, 12 Apr 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/cover.jpg" alt="Featured image of post Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)" /><h2 id="1microsoft-visual-c-140安装">1、Microsoft Visual C++ 14.0安装 +</h2><p>这里附上百度网盘下载链接: +链接: <a class="link" href="https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88</a> 提取码: ec88</p> +<p>下载完成后双击打开 +<img src="https://img-blog.csdnimg.cn/04150c3c158c4baab13f0646ab6bb578.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>默认下载方式即可</p> +<hr> +<h2 id="2pycocotools20版本安装">2、Pycocotools2.0版本安装 +</h2><h4 id="1准备材料">(1)准备材料: +</h4><ul> +<li><a class="link" href="https://github.com/cocodataset/cocoapi" target="_blank" rel="noopener" +>下载pycocotools安装包</a>(可直接git拉取到本地文件夹)</li> +</ul> +<h4 id="2源码配置">(2)源码配置 +</h4><p>打开下载好的pycocotools,双击打开<code>setup.py</code>(文件路径:\cocoapi\PythonAPI\setup.py)</p> +<p><img src="https://img-blog.csdnimg.cn/985a37a42b1043bc9dc87d3c3e4e1d0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这里<code>将蓝色部分删除,只保留红色部分</code>(切记需要执行这一步!!!)</p> +<p>开始界面找到所有应用并打开<code>Anaconda Powershell Prompt</code></p> +<p><img src="https://img-blog.csdnimg.cn/9ad6e210127c49c9bfb16f9fd9b65968.png" +loading="lazy" +></p> +<p>先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。</p> +<p>如上图所示进入到<code>\cocoapi\PythonAPI</code>该目录下</p> +<p>分别执行以下两个命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="o">--</span><span class="n">inplace</span> +</span></span><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="n">install</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/02ec23e44b3848609cc74c8c28368a0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>执行pip list查看</p> +<p><img src="https://img-blog.csdnimg.cn/642adca979d64daba7f8d2164e88443c.png" +loading="lazy" +> +此时回到<code>\cocoapi\PythonAPI</code>目录下,可以看到生成了相关文件 +<img src="https://img-blog.csdnimg.cn/bdde5563cb794cf1962800f4656b71f5.png" +loading="lazy" +alt="在这里插入图片描述" +> +将<code>pycocotools</code>和<code>pycocotools.egg-info</code>文件夹复制到你所创建的虚拟环境中(位置:Anaconda3-&gt;envs-&gt;python_env-&gt;Lib-&gt;site-packages) +<img src="https://img-blog.csdnimg.cn/8dd05ee9c4724de4a2ba536ad84aec81.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>至此所有问题解决!</p>总结:开发板挂载根文件系统遇到的一些问题https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/Wed, 30 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/cover.jpg" alt="Featured image of post 总结:开发板挂载根文件系统遇到的一些问题" /><h2 id="一桥接网络">一、桥接网络 +</h2><h4 id="1简介">1、简介 +</h4><p>是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址</p> +<h4 id="注意避坑">注意避坑: +</h4><p>如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。</p> +<h4 id="2解决办法">2、解决办法: +</h4><p>&lt;1&gt;选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241318456.png" +loading="lazy" +alt="image-20230424131854375" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241319850.png" +loading="lazy" +alt="image-20230424131957782" +></p> +<p>&lt;2&gt;无线网卡连接</p> +<p>考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)</p> +<p>如下配置:</p> +<ul> +<li>主机配置</li> +</ul> +<p>首先电脑win+R,输入<code>cmd</code>进入终端,然后输入命令:<code>ipconfig</code>,找到自己的热点网络信息</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320409.png" +loading="lazy" +alt="image-20230424132028276" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320692.png" +loading="lazy" +alt="image-20230424132041431" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241321679.png" +loading="lazy" +alt="image-20230424132117501" +></p> +<ul> +<li>虚拟机配置</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322849.png" +loading="lazy" +alt="image-20230424132214739" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322385.png" +loading="lazy" +alt="image-20230424132233318" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322519.png" +loading="lazy" +alt="image-20230424132250210" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">保存退出后,再次输入命令: +</span></span><span class="line"><span class="cl">首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡) +</span></span><span class="line"><span class="cl">然后启用网卡:ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="二开发板端测试">二、开发板端测试: +</h2><p><code>以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客</code></p> +<p><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124407302?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【Linux系统开发】x210开发板根目录文件系统构建</a></p> +<p>我们打开secureCRT:</p> +<p>开机先ping下虚拟机网络:<code>ping '虚拟机IP'</code></p> +<blockquote> +<p>注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="err">方法一:打开命令:</span><span class="n">sudo</span> <span class="n">gedit</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">NetworkManager</span><span class="o">/</span><span class="n">nm</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">settings</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">出现文件内容:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># This file is installed into /etc/NetworkManager, and is loaded by</span> +</span></span><span class="line"><span class="cl"><span class="c1"># NetworkManager by default. To override, specify: &#39;--config file&#39;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># during NM startup. This can be done by appending to DAEMON_OPTS in</span> +</span></span><span class="line"><span class="cl"><span class="c1"># the file:</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"><span class="c1"># /etc/default/NetworkManager</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">main</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">plugins</span><span class="o">=</span><span class="n">ifupdown</span><span class="p">,</span><span class="n">keyfile</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">ifupdown</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">managed</span><span class="o">=</span><span class="bp">true</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">(这里</span><span class="n">false改成true</span><span class="err">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">方法二:虚拟机重置网卡 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ifdown eth0 +</span></span><span class="line"><span class="cl">ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>当开发板ping通虚拟机后,我们在secureCRT控制台输入<code>reset</code>命令重启开发板</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323671.png" +loading="lazy" +alt="image-20230424132308595" +></p> +<p>这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323776.png" +loading="lazy" +alt="image-20230424132323723" +></p> +<p>解决:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mount -t nfs -o nolock &#39;开发板ipaddr ip&#39;:/root/rootfs/x210_rootfs //再次重新挂载根文件系统 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//NFC网络重启 +</span></span><span class="line"><span class="cl">/etc/init.d/nfs-kernel-server restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323050.png" +loading="lazy" +alt="image-20230424132335917" +></p> +<p>问题解决!</p>多线程技术学习(基于Linux)https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post 多线程技术学习(基于Linux)" /><h2 id="1linux多线程概念">1.Linux多线程概念 +</h2><blockquote> +<p><strong>(1)线程:指运行中的程序的调度单位。</strong></p> +</blockquote> +<blockquote> +<p><strong>(2)多线程的优点:</strong></p> +</blockquote> +<ul> +<li>运行与一个线程中的多个线程,他们彼此之间使用<strong>相同的地址空间</strong>,<strong>共享大部分数据</strong>,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。</li> +<li>进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式</li> +<li>应用程序响应速度提高</li> +<li>使多CPU系统更加高效</li> +<li>改善程序结构</li> +</ul> +<blockquote> +<p><strong>(3)线程的生命周期</strong></p> +</blockquote> +<p>就绪-&gt;运行-&gt;阻塞-&gt;终止</p> +<hr> +<h2 id="2linux线程实现">2.linux线程实现 +</h2><blockquote> +<p><strong>(1)线程创建</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含 +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) +</code></pre> +</li> +<li> +<p>函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数 <br> +arg: start_rtn的参数</p> +</li> +</ul> +<blockquote> +<p><strong>(2)线程退出</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +void pthread_exit(void * rval_ptr)</li> +<li>功能:终止调用线程Rval_ptr:线程退出返回值的指针。</li> +</ul> +<blockquote> +<p><strong>(3)线程等待</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_join(pthread_t tid,void **rval_ptr) +</code></pre> +</li> +<li> +<p>功能:阻塞调用线程,直到指定的线程终止。</p> +</li> +<li> +<p>函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针</p> +</li> +</ul> +<blockquote> +<p><strong>(4)线程标识获取</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +pthread_t pthread_self(void)</li> +<li>功能:获取调用线程的 thread identifier</li> +</ul> +<blockquote> +<p><strong>(5)线程清除</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> void pthread_cleanup_push(void (*rtn)(void *),void *arg) +</code></pre> +</li> +<li> +<p>功能:将清除函数压入清除栈</p> +</li> +<li> +<p>函数说明: +Rtn:清除函数 +Arg:清除函数的参数</p> +</li> +</ul> +<hr> +<h2 id="3线程同步的方法">3.线程同步的方法 +</h2><p>进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:</p> +<blockquote> +<p>互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions</p> +</blockquote> +<hr> +<h2 id="4线程的互斥">4.线程的互斥 +</h2><p>线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。</p> +<blockquote> +<p><strong>(1)创建</strong></p> +</blockquote> +<p>在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:</p> +<ul> +<li>对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER</li> +<li>对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。</li> +</ul> +<blockquote> +<p>函数使用: +头文件: +#include &lt;pthread.h&gt;</p> +</blockquote> +<pre><code>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) +int pthread_mutex_destroy(pthread_mutex_t *mutex) +</code></pre> +<blockquote> +<p><strong>(2)加锁</strong></p> +</blockquote> +<p>对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。</p> +<blockquote> +<p>函数使用:</p> +</blockquote> +<pre><code>int pthread_mutex_lock(pthread_mutex_t *mutex) +int pthread_mutex_trylock(pthread_mutex_t *mutex) +</code></pre> +<p>返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。</p> +<blockquote> +<p><strong>(3)解锁</strong></p> +</blockquote> +<p>在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。</p> +<pre><code>int pthread_mutex_unlock(pthread_mutex_t *mutex) +</code></pre> +<hr> +<h2 id="5互斥pk信号量">5.互斥PK信号量 +</h2><blockquote> +<p>Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:</p> +<ol> +<li>mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放</li> +<li>初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。</li> +</ol> +</blockquote> +<hr> +<h2 id="6信号量操作代码演示">6.信号量操作(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;semaphore.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">sem_t sem; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sem_wait(&amp;sem); // 接收信号量 +</span></span><span class="line"><span class="cl"> /* +</span></span><span class="line"><span class="cl"> Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 +</span></span><span class="line"><span class="cl"> 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> //while(strncmp(buf,&#34;end&#34;,3) != 0) +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> sem_init(&amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(scanf(&#34;%s&#34;,buf)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> sem_post(&amp;sem); //增加(解锁)sem指向的信号量 +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="7互斥操作函数演示">7.互斥操作(函数演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">pthread_mutex_t mutex; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sleep(1); +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 互斥加锁 +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 解锁 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_mutex_init(&amp;mutex,NULL); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 对互斥对象加锁锁定 +</span></span><span class="line"><span class="cl"> scanf(&#34;%s&#34;,buf); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 输入后解锁 +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> pthread_mutex_destroy(&amp;mutex); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="8条件变量代码演示">8.条件变量(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1">#include&lt;stdio.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;string.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;pthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;stdlib.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">子线程处理</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_cond_t</span> <span class="n">cond</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">flag</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="o">*</span><span class="k">func</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">flag</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span><span class="o">//</span> <span class="err">互斥加锁</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span><span class="o">//</span> <span class="err">线程同步等待</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> <span class="o">//</span> <span class="err">解锁</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_exit</span><span class="p">(</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_t</span> <span class="n">th</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="err">初始化条件变量</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">,</span><span class="k">func</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_create</span><span class="p">()</span><span class="err">函数在调用进程中启动一个新线程</span><span class="p">,</span><span class="err">创建成功返回</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_create error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;please input string,end with Enter.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">scanf</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">发送信号</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="s2">&#34;end&#34;</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;process end</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char .</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;wait reclaim child thread.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">函数等待由</span><span class="n">thread指定的线程结束</span><span class="err">。如果该线程已经终止,则</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">立即返回。</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_join error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;reclaim child thread successfully.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">条件变量销毁</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>信号量及PV操作详解https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/Thu, 10 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 信号量及PV操作详解" /><h2 id="信号量">信号量 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->一个特殊变量</li> +<li><!-- raw HTML omitted -->用于进程间传递信息的一个整数值</li> +</ul> +</blockquote> +<p>定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct semaphore +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int count; +</span></span><span class="line"><span class="cl"> quenue Type quenue; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<ul> +<li><!-- raw HTML omitted -->信号量说明:semaphore s;</li> +<li><!-- raw HTML omitted -->对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen))</li> +</ul> +</blockquote> +<h2 id="pv操作定义">P、V操作定义 +</h2><p><!-- raw HTML omitted -->P(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.count --; //信号量值减一 +</span></span><span class="line"><span class="cl"> if(s.count&lt;0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 该进程状态置为阻塞态; +</span></span><span class="line"><span class="cl"> 将该进程插入相应的等待队列s.quenue末尾; +</span></span><span class="line"><span class="cl"> 重新调度 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>down</code>,<code>semwait</code>:也代表P操作</p> +<p><!-- raw HTML omitted -->V(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.ount++; +</span></span><span class="line"><span class="cl"> if(s.count&lt;=0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 唤醒相应等待队列s.queue中等待的一个进程; +</span></span><span class="line"><span class="cl"> 改变其状态为就绪态,并将其插入就绪队列; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>up</code>,<code>semsignal</code>:也代表V操作</p> +<blockquote> +<p>相关说明</p> +<ul> +<li><!-- raw HTML omitted -->P,V操作为原语操作</li> +<li><!-- raw HTML omitted -->在信号量上定义了三个操作 +<!-- raw HTML omitted -->初始化(非负数)、P操作、V操作<!-- raw HTML omitted --></li> +<li><!-- raw HTML omitted -->最初提出的是二元信号量(解决互斥) +之后,推广到一般信号量(多值)或技术信号量(解决同步)</li> +</ul> +</blockquote> +<h2 id="用pv操作解决进程间互斥问题">用PV操作解决进程间互斥问题 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->分析并发进程的关键活动,划定临界区</li> +<li><!-- raw HTML omitted -->设置信号量mutux,初值为1</li> +<li><!-- raw HTML omitted -->在临界区前实施P(mutux)</li> +<li><!-- raw HTML omitted -->在临界区之后实施V(mutux)</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/9f7d7a26cf6a41048d7205423383fa64.png" +loading="lazy" +alt="图片演示" +></p> +<blockquote> +<p>相关解释:</p> +</blockquote> +<ul> +<li> +<p><code>临界区</code> : 我们把并发进程中与共享变量有关的程序段称为临界区。</p> +</li> +<li> +<p><code>信号量</code> : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。</p> +</li> +<li> +<p><code>进程的互斥</code>:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。</p> +</li> +<li> +<p><code>进程的同步</code>:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。</p> +</li> +<li> +<p><code>pv操作又称wait,signal原语。</code> +主要是操作进程中对进程控制的信息量的加减控制。</p> +</li> +</ul> +<blockquote> +<p><!-- raw HTML omitted --><code>注意:</code>在霍尔管程中,<code>wait操作</code>和<code>signal操作</code>用于被设计为两个可以中断的过程,而非<code>原语。</code> +<!-- raw HTML omitted -->在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 +条件变量的两种操作:</p> +<ul> +<li>wait()操作<!-- raw HTML omitted -->[阻塞调用进程]<!-- raw HTML omitted --></li> +<li>signal()操作<!-- raw HTML omitted -->[释放/唤醒在条件变量上阻塞的进程]<!-- raw HTML omitted --></li> +</ul> +</blockquote> +<ul> +<li>wait用法: +wait(num),num是目标参数,wait的作用是使其(信息量)减一。 +如果信息量&gt;=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 +signal用法: +signal(num),num是目标参数,signal的作用是使其(信息量)加一。 +如果信息量&gt;0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。</li> +</ul> +<blockquote> +<p>本文资源来自<a class="link" href="https://www.coursera.org/learn/os-pku" target="_blank" rel="noopener" +>Operating Systems</a> +参考:<a class="link" href="https://blog.csdn.net/thebestway/article/details/105034840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164992015416780255296134%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=164992015416780255296134&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-105034840.142%5ev8%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=wait%E5%92%8Csignal%E5%8E%9F%E8%AF%AD&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>操作系统P,V(wait,signal原语)操作讲解</a></p> +</blockquote>进程上下文和线程上下文https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/Tue, 08 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/cover.jpg" alt="Featured image of post 进程上下文和线程上下文" /><h2 id="进程">进程 +</h2><p><code>操作系统资源分配的基本单位</code>,也就是指计算机中已执行的程序。</p> +<ul> +<li>在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,<code>进程</code>是程序的基本执行实体;</li> +<li>在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是<code>线程</code>的容器。</li> +<li>程序本身只是指令、数据及其组织形式的描述,相当于一个名词,<code>进程</code>才是程序(那些指令和数据)的真正<code>执行实例</code>.</li> +</ul> +<h2 id="进程上下文">进程上下文 +</h2><p><code>进程上下文</code>就是表示<code>进程信息</code>的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。</p> +<p>拿<code>Linux进程</code>举例: +&mdash;-进程的运行环境主要包括:</p> +<blockquote> +<p>1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 +2.环境变量:提供进程运行所需的环境信息。 +3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 +4.进程访问设备或者文件时的权限。 +5.各种硬件寄存器。 +6.地址转换信息。</p> +</blockquote> +<p>由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。</p> +<h2 id="线程">线程 +</h2><p><code>操作系统能够进行运算调度的最小单位</code>。</p> +<ul> +<li>大部分情况下,它被包含在进程之中,是进程中的实际运作单位。</li> +<li>一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。</li> +<li>线程是独立调度和分派的基本单位。 +线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。</li> +<li>同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。</li> +</ul> +<h2 id="线程上下文">线程上下文 +</h2><p>进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。<code>同样的,线程也有上下文。</code></p> +<blockquote> +<p>当线程被抢占时,就会发生线程之间的上下文切换。 +如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。</p> +</blockquote> +<p>线程上下文与进程上下文对比</p> +<table> +<thead> +<tr> +<th>上下文内容</th> +<th>进程</th> +<th>线程</th> +</tr> +</thead> +<tbody> +<tr> +<td>指向可执行文件的指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>栈</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>内存(数据段和堆)</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>状态</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>优先级</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>程序IO的状态</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>授予权限</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>调度信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>审计信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件描述符</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件读/写指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>寄存器组</td> +<td>×</td> +<td>×</td> +</tr> +</tbody> +</table>Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p> \ No newline at end of file diff --git a/post/page/1/index.html b/post/page/1/index.html new file mode 100644 index 000000000..2817935f4 --- /dev/null +++ b/post/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/post/ + \ No newline at end of file diff --git a/post/page/10/index.html b/post/page/10/index.html new file mode 100644 index 000000000..95d476d56 --- /dev/null +++ b/post/page/10/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/11/index.html b/post/page/11/index.html new file mode 100644 index 000000000..9d6dc0070 --- /dev/null +++ b/post/page/11/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/12/index.html b/post/page/12/index.html new file mode 100644 index 000000000..8eb2db3f5 --- /dev/null +++ b/post/page/12/index.html @@ -0,0 +1,60 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/13/index.html b/post/page/13/index.html new file mode 100644 index 000000000..15977bdd5 --- /dev/null +++ b/post/page/13/index.html @@ -0,0 +1,59 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/14/index.html b/post/page/14/index.html new file mode 100644 index 000000000..a3f50e451 --- /dev/null +++ b/post/page/14/index.html @@ -0,0 +1,58 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/2/index.html b/post/page/2/index.html new file mode 100644 index 000000000..b08fc6c5c --- /dev/null +++ b/post/page/2/index.html @@ -0,0 +1,59 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/3/index.html b/post/page/3/index.html new file mode 100644 index 000000000..1860d9e8e --- /dev/null +++ b/post/page/3/index.html @@ -0,0 +1,60 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/4/index.html b/post/page/4/index.html new file mode 100644 index 000000000..795b44a1a --- /dev/null +++ b/post/page/4/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/5/index.html b/post/page/5/index.html new file mode 100644 index 000000000..98f446a60 --- /dev/null +++ b/post/page/5/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/6/index.html b/post/page/6/index.html new file mode 100644 index 000000000..08e5ceaf7 --- /dev/null +++ b/post/page/6/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/7/index.html b/post/page/7/index.html new file mode 100644 index 000000000..7d9a46678 --- /dev/null +++ b/post/page/7/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/8/index.html b/post/page/8/index.html new file mode 100644 index 000000000..0de563517 --- /dev/null +++ b/post/page/8/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/post/page/9/index.html b/post/page/9/index.html new file mode 100644 index 000000000..883c72b88 --- /dev/null +++ b/post/page/9/index.html @@ -0,0 +1,61 @@ +Posts +

Section

70 pages

Posts

\ No newline at end of file diff --git a/quote/index.html b/quote/index.html new file mode 100644 index 000000000..41b78ab4d --- /dev/null +++ b/quote/index.html @@ -0,0 +1,24 @@ +Quote +

Quote

+

📑读书 学习 去更远的地方


每个人手上都拿着一张随时可能会输的牌,在人生中寻找补救的方法。

星野道夫, 《在漫长的旅途中》

人只有在举棋不定,无从把握的时候才感到疲惫。只有去行动就能获得解放,哪怕做的不好也比无所作为强。

斯蒂夫·茨威格, 《创世纪》

虚心佐我闪光 谦卑助我制胜 德行辅我压迫

阿尔贝·加缪, 《堕落》
+Licensed under CC BY-NC-SA 4.0
顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy
\ No newline at end of file diff --git a/quote/travel.mp4 b/quote/travel.mp4 new file mode 100644 index 000000000..0962ec10c Binary files /dev/null and b/quote/travel.mp4 differ diff --git a/scss/style.min.0304c6baf04e01a8fe70693791cb744d56a3578a3120a8796cefc66825aa39c7.css b/scss/style.min.0304c6baf04e01a8fe70693791cb744d56a3578a3120a8796cefc66825aa39c7.css new file mode 100644 index 000000000..05314a4a8 --- /dev/null +++ b/scss/style.min.0304c6baf04e01a8fe70693791cb744d56a3578a3120a8796cefc66825aa39c7.css @@ -0,0 +1,10 @@ +/*!* Hugo Theme Stack +* +* @author: Jimmy Cai +* @website: https://jimmycai.com +* @link: https://github.com/CaiJimmy/hugo-theme-stack*/:root{--main-top-padding:35px;--body-background:#f5f5fa;--accent-color:#34495e;--accent-color-darker:#2c3e50;--accent-color-text:#fff;--body-text-color:#707070;--tag-border-radius:4px;--section-separation:40px;--scrollbar-thumb:hsl(0, 0%, 85%);--scrollbar-track:var(--body-background)}@media(min-width:1280px){:root{--main-top-padding:50px}}:root[data-scheme=dark]{--body-background:#303030;--accent-color:#ecf0f1;--accent-color-darker:#bdc3c7;--accent-color-text:#000;--body-text-color:rgba(255, 255, 255, 0.7);--scrollbar-thumb:hsl(0, 0%, 40%);--scrollbar-track:var(--body-background)}:root{--sys-font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", "Droid Sans", "Helvetica Neue";--zh-font-family:"PingFang SC", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei";--base-font-family:"Lato", var(--sys-font-family), var(--zh-font-family), sans-serif;--code-font-family:Menlo, Monaco, Consolas, "Courier New", var(--zh-font-family), monospace}:root{--card-background:#fff;--card-background-selected:#eaeaea;--card-text-color-main:#000;--card-text-color-secondary:#747474;--card-text-color-tertiary:#767676;--card-separator-color:rgba(218, 218, 218, 0.5);--card-border-radius:10px;--card-padding:20px;--small-card-padding:25px 20px}@media(min-width:768px){:root{--card-padding:25px}}@media(min-width:1280px){:root{--card-padding:30px}}@media(min-width:768px){:root{--small-card-padding:25px}}:root[data-scheme=dark]{--card-background:#424242;--card-background-selected:rgba(255, 255, 255, 0.16);--card-text-color-main:rgba(255, 255, 255, 0.9);--card-text-color-secondary:rgba(255, 255, 255, 0.7);--card-text-color-tertiary:rgba(255, 255, 255, 0.5);--card-separator-color:rgba(255, 255, 255, 0.12)}:root{--article-font-family:var(--base-font-family);--article-font-size:1.6rem;--article-line-height:1.85}@media(min-width:768px){:root{--article-font-size:1.7rem}}:root{--blockquote-border-size:4px;--blockquote-background-color:rgb(248 248 248);--heading-border-size:4px;--link-background-color:189, 195, 199;--link-background-opacity:0.5;--link-background-opacity-hover:0.7;--pre-background-color:#272822;--pre-text-color:#f8f8f2;--code-background-color:rgba(0, 0, 0, 0.12);--code-text-color:#808080;--table-border-color:#dadada;--tr-even-background-color:#efefee;--kbd-border-color:#dadada}:root[data-scheme=dark]{--code-background-color:#272822;--code-text-color:rgba(255, 255, 255, 0.9);--table-border-color:#717171;--tr-even-background-color:#545454;--blockquote-background-color:rgb(75 75 75)}:root{--shadow-l1:0px 4px 8px rgba(0, 0, 0, 0.04), 0px 0px 2px rgba(0, 0, 0, 0.06), 0px 0px 1px rgba(0, 0, 0, 0.04);--shadow-l2:0px 10px 20px rgba(0, 0, 0, 0.04), 0px 2px 6px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04);--shadow-l3:0px 10px 20px rgba(0, 0, 0, 0.04), 0px 2px 6px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04);--shadow-l4:0px 24px 32px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), + 0px 0px 1px rgba(0, 0, 0, 0.04)}[data-scheme=light]{--pre-text-color:#272822;--pre-background-color:#fafafa}[data-scheme=light] .chroma{color:#272822;background-color:#fafafa}[data-scheme=light] .chroma .err{color:#960050}[data-scheme=light] .chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}[data-scheme=light] .chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:100%;display:block}[data-scheme=light] .chroma .lntable>tbody{display:block;width:100%}[data-scheme=light] .chroma .lntable>tbody>tr{display:flex;width:100%}[data-scheme=light] .chroma .lntable>tbody>tr>td:last-child{overflow-x:auto}[data-scheme=light] .chroma .hl{display:block;width:100%;background-color:#ffc}[data-scheme=light] .chroma .lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f;display:block}[data-scheme=light] .chroma .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}[data-scheme=light] .chroma .k{color:#00a8c8}[data-scheme=light] .chroma .kc{color:#00a8c8}[data-scheme=light] .chroma .kd{color:#00a8c8}[data-scheme=light] .chroma .kn{color:#f92672}[data-scheme=light] .chroma .kp{color:#00a8c8}[data-scheme=light] .chroma .kr{color:#00a8c8}[data-scheme=light] .chroma .kt{color:#00a8c8}[data-scheme=light] .chroma .n{color:#111}[data-scheme=light] .chroma .na{color:#75af00}[data-scheme=light] .chroma .nb{color:#111}[data-scheme=light] .chroma .bp{color:#111}[data-scheme=light] .chroma .nc{color:#75af00}[data-scheme=light] .chroma .no{color:#00a8c8}[data-scheme=light] .chroma .nd{color:#75af00}[data-scheme=light] .chroma .ni{color:#111}[data-scheme=light] .chroma .ne{color:#75af00}[data-scheme=light] .chroma .nf{color:#75af00}[data-scheme=light] .chroma .fm{color:#111}[data-scheme=light] .chroma .nl{color:#111}[data-scheme=light] .chroma .nn{color:#111}[data-scheme=light] .chroma .nx{color:#75af00}[data-scheme=light] .chroma .py{color:#111}[data-scheme=light] .chroma .nt{color:#f92672}[data-scheme=light] .chroma .nv{color:#111}[data-scheme=light] .chroma .vc{color:#111}[data-scheme=light] .chroma .vg{color:#111}[data-scheme=light] .chroma .vi{color:#111}[data-scheme=light] .chroma .vm{color:#111}[data-scheme=light] .chroma .l{color:#ae81ff}[data-scheme=light] .chroma .ld{color:#d88200}[data-scheme=light] .chroma .s{color:#d88200}[data-scheme=light] .chroma .sa{color:#d88200}[data-scheme=light] .chroma .sb{color:#d88200}[data-scheme=light] .chroma .sc{color:#d88200}[data-scheme=light] .chroma .dl{color:#d88200}[data-scheme=light] .chroma .sd{color:#d88200}[data-scheme=light] .chroma .s2{color:#d88200}[data-scheme=light] .chroma .se{color:#ae81ff}[data-scheme=light] .chroma .sh{color:#d88200}[data-scheme=light] .chroma .si{color:#d88200}[data-scheme=light] .chroma .sx{color:#d88200}[data-scheme=light] .chroma .sr{color:#d88200}[data-scheme=light] .chroma .s1{color:#d88200}[data-scheme=light] .chroma .ss{color:#d88200}[data-scheme=light] .chroma .m{color:#ae81ff}[data-scheme=light] .chroma .mb{color:#ae81ff}[data-scheme=light] .chroma .mf{color:#ae81ff}[data-scheme=light] .chroma .mh{color:#ae81ff}[data-scheme=light] .chroma .mi{color:#ae81ff}[data-scheme=light] .chroma .il{color:#ae81ff}[data-scheme=light] .chroma .mo{color:#ae81ff}[data-scheme=light] .chroma .o{color:#f92672}[data-scheme=light] .chroma .ow{color:#f92672}[data-scheme=light] .chroma .p{color:#111}[data-scheme=light] .chroma .c{color:#75715e}[data-scheme=light] .chroma .ch{color:#75715e}[data-scheme=light] .chroma .cm{color:#75715e}[data-scheme=light] .chroma .c1{color:#75715e}[data-scheme=light] .chroma .cs{color:#75715e}[data-scheme=light] .chroma .cp{color:#75715e}[data-scheme=light] .chroma .cpf{color:#75715e}[data-scheme=light] .chroma .gd{color:#f92672}[data-scheme=light] .chroma .ge{font-style:italic}[data-scheme=light] .chroma .gi{color:#75af00}[data-scheme=light] .chroma .gs{font-weight:700}[data-scheme=light] .chroma .gu{color:#75715e}[data-scheme=dark]{--pre-text-color:#f8f8f2;--pre-background-color:#272822}[data-scheme=dark] .chroma{color:#f8f8f2;background-color:#272822}[data-scheme=dark] .chroma .err{color:#bb0064}[data-scheme=dark] .chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}[data-scheme=dark] .chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:100%;display:block}[data-scheme=dark] .chroma .lntable>tbody{display:block;width:100%}[data-scheme=dark] .chroma .lntable>tbody>tr{display:flex;width:100%}[data-scheme=dark] .chroma .lntable>tbody>tr>td:last-child{overflow-x:auto}[data-scheme=dark] .chroma .hl{display:block;width:100%;background-color:#ffc}[data-scheme=dark] .chroma .lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f;display:block}[data-scheme=dark] .chroma .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}[data-scheme=dark] .chroma .k{color:#66d9ef}[data-scheme=dark] .chroma .kc{color:#66d9ef}[data-scheme=dark] .chroma .kd{color:#66d9ef}[data-scheme=dark] .chroma .kn{color:#f92672}[data-scheme=dark] .chroma .kp{color:#66d9ef}[data-scheme=dark] .chroma .kr{color:#66d9ef}[data-scheme=dark] .chroma .kt{color:#66d9ef}[data-scheme=dark] .chroma .n{color:#f8f8f2}[data-scheme=dark] .chroma .na{color:#a6e22e}[data-scheme=dark] .chroma .nb{color:#f8f8f2}[data-scheme=dark] .chroma .bp{color:#f8f8f2}[data-scheme=dark] .chroma .nc{color:#a6e22e}[data-scheme=dark] .chroma .no{color:#66d9ef}[data-scheme=dark] .chroma .nd{color:#a6e22e}[data-scheme=dark] .chroma .ni{color:#f8f8f2}[data-scheme=dark] .chroma .ne{color:#a6e22e}[data-scheme=dark] .chroma .nf{color:#a6e22e}[data-scheme=dark] .chroma .fm{color:#f8f8f2}[data-scheme=dark] .chroma .nl{color:#f8f8f2}[data-scheme=dark] .chroma .nn{color:#f8f8f2}[data-scheme=dark] .chroma .nx{color:#a6e22e}[data-scheme=dark] .chroma .py{color:#f8f8f2}[data-scheme=dark] .chroma .nt{color:#f92672}[data-scheme=dark] .chroma .nv{color:#f8f8f2}[data-scheme=dark] .chroma .vc{color:#f8f8f2}[data-scheme=dark] .chroma .vg{color:#f8f8f2}[data-scheme=dark] .chroma .vi{color:#f8f8f2}[data-scheme=dark] .chroma .vm{color:#f8f8f2}[data-scheme=dark] .chroma .l{color:#ae81ff}[data-scheme=dark] .chroma .ld{color:#e6db74}[data-scheme=dark] .chroma .s{color:#e6db74}[data-scheme=dark] .chroma .sa{color:#e6db74}[data-scheme=dark] .chroma .sb{color:#e6db74}[data-scheme=dark] .chroma .sc{color:#e6db74}[data-scheme=dark] .chroma .dl{color:#e6db74}[data-scheme=dark] .chroma .sd{color:#e6db74}[data-scheme=dark] .chroma .s2{color:#e6db74}[data-scheme=dark] .chroma .se{color:#ae81ff}[data-scheme=dark] .chroma .sh{color:#e6db74}[data-scheme=dark] .chroma .si{color:#e6db74}[data-scheme=dark] .chroma .sx{color:#e6db74}[data-scheme=dark] .chroma .sr{color:#e6db74}[data-scheme=dark] .chroma .s1{color:#e6db74}[data-scheme=dark] .chroma .ss{color:#e6db74}[data-scheme=dark] .chroma .m{color:#ae81ff}[data-scheme=dark] .chroma .mb{color:#ae81ff}[data-scheme=dark] .chroma .mf{color:#ae81ff}[data-scheme=dark] .chroma .mh{color:#ae81ff}[data-scheme=dark] .chroma .mi{color:#ae81ff}[data-scheme=dark] .chroma .il{color:#ae81ff}[data-scheme=dark] .chroma .mo{color:#ae81ff}[data-scheme=dark] .chroma .o{color:#f92672}[data-scheme=dark] .chroma .ow{color:#f92672}[data-scheme=dark] .chroma .p{color:#f8f8f2}[data-scheme=dark] .chroma .c{color:#75715e}[data-scheme=dark] .chroma .ch{color:#75715e}[data-scheme=dark] .chroma .cm{color:#75715e}[data-scheme=dark] .chroma .c1{color:#75715e}[data-scheme=dark] .chroma .cs{color:#75715e}[data-scheme=dark] .chroma .cp{color:#75715e}[data-scheme=dark] .chroma .cpf{color:#75715e}[data-scheme=dark] .chroma .gd{color:#f92672}[data-scheme=dark] .chroma .ge{font-style:italic}[data-scheme=dark] .chroma .gi{color:#a6e22e}[data-scheme=dark] .chroma .gs{font-weight:700}[data-scheme=dark] .chroma .gu{color:#75715e}:root{--menu-icon-separation:40px;--container-padding:15px;--widget-separation:var(--section-separation)}.container{margin-left:auto;margin-right:auto}.container .left-sidebar{order:-3;max-width:var(--left-sidebar-max-width)}.container .right-sidebar{order:-1;max-width:var(--right-sidebar-max-width)}@media(min-width:1024px){.container .right-sidebar{display:flex}}@media(min-width:768px){.container.extended{max-width:1024px;--left-sidebar-max-width:25%;--right-sidebar-max-width:30%}}@media(min-width:1024px){.container.extended{max-width:1280px;--left-sidebar-max-width:20%;--right-sidebar-max-width:30%}}@media(min-width:1280px){.container.extended{max-width:1536px;--left-sidebar-max-width:15%;--right-sidebar-max-width:25%}}@media(min-width:768px){.container.compact{--left-sidebar-max-width:25%;max-width:768px}}@media(min-width:1024px){.container.compact{max-width:1024px;--left-sidebar-max-width:20%}}@media(min-width:1280px){.container.compact{max-width:1280px}}.flex{display:flex;flex-direction:row}.flex.column{flex-direction:column}.flex.on-phone--column{flex-direction:column}@media(min-width:768px){.flex.on-phone--column{flex-direction:unset}}.flex .full-width{width:100%}main.main{order:-2;min-width:0;max-width:100%;flex-grow:1;display:flex;flex-direction:column;gap:var(--section-separation)}@media(min-width:768px){main.main{padding-top:var(--main-top-padding)}}.main-container{min-height:100vh;align-items:flex-start;padding:0 15px;gap:var(--section-separation);padding-top:var(--main-top-padding)}@media(min-width:768px){.main-container{padding:0 20px}}/*!normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}/*!* Hamburgers +* @description Tasty CSS-animated hamburgers +* @author Jonathan Suh @jonsuh +* @site https://jonsuh.com/hamburgers +* @link https://github.com/jonsuh/hamburgers*/.hamburger{padding-top:10px;display:inline-block;cursor:pointer;transition-property:opacity,filter;transition-duration:.15s;transition-timing-function:linear;font:inherit;color:inherit;text-transform:none;background-color:transparent;border:0;margin:0;overflow:visible}.hamburger:hover{opacity:.7}.hamburger.is-active:hover{opacity:.7}.hamburger.is-active .hamburger-inner,.hamburger.is-active .hamburger-inner::before,.hamburger.is-active .hamburger-inner::after{background-color:#000}.hamburger-box{width:30px;height:24px;display:inline-block;position:relative}.hamburger-inner{display:block;top:50%;margin-top:-2px}.hamburger-inner,.hamburger-inner::before,.hamburger-inner::after{width:30px;height:2px;background-color:var(--card-text-color-main);border-radius:4px;position:absolute;transition-property:transform;transition-duration:.15s;transition-timing-function:ease}.hamburger-inner::before,.hamburger-inner::after{content:"";display:block}.hamburger-inner::before{top:-10px}.hamburger-inner::after{bottom:-10px}.hamburger--spin .hamburger-inner{transition-duration:.22s;transition-timing-function:cubic-bezier(.55,.055,.675,.19)}.hamburger--spin .hamburger-inner::before{transition:top .1s .25s ease-in,opacity .1s ease-in}.hamburger--spin .hamburger-inner::after{transition:bottom .1s .25s ease-in,transform .22s cubic-bezier(.55,.055,.675,.19)}.hamburger--spin.is-active .hamburger-inner{transform:rotate(225deg);transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1)}.hamburger--spin.is-active .hamburger-inner::before{top:0;opacity:0;transition:top .1s ease-out,opacity .1s .12s ease-out}.hamburger--spin.is-active .hamburger-inner::after{bottom:0;transform:rotate(-90deg);transition:bottom .1s ease-out,transform .22s .12s cubic-bezier(.215,.61,.355,1)}#toggle-menu{background:0 0;border:none;position:absolute;right:0;top:0;z-index:2;cursor:pointer;outline:none}[dir=rtl] #toggle-menu{left:0;right:auto}@media(min-width:768px){#toggle-menu{display:none}}#toggle-menu.is-active .hamburger-inner,#toggle-menu.is-active .hamburger-inner::before,#toggle-menu.is-active .hamburger-inner::after{background-color:var(--accent-color)}#main-menu{list-style:none;overflow-y:auto;flex-grow:1;font-size:1.4rem;background-color:var(--card-background);box-shadow:var(--shadow-l1);display:none;margin:0 calc(var(--container-padding) * -1);padding:30px}@media(min-width:1280px){#main-menu{padding:15px 0}}#main-menu,#main-menu .menu-bottom-section ol{flex-direction:column;gap:30px}@media(min-width:1280px){#main-menu,#main-menu .menu-bottom-section ol{gap:25px}}#main-menu.show{display:flex}@media(min-width:768px){#main-menu{align-items:flex-end;display:flex;background-color:transparent;padding:0;box-shadow:none;margin:0}}#main-menu li{position:relative;vertical-align:middle;padding:0}@media(min-width:768px){#main-menu li{width:100%}}#main-menu li svg{stroke:currentColor;stroke-width:1.33;width:20px;height:20px}#main-menu li a{height:100%;display:inline-flex;align-items:center;color:var(--body-text-color);gap:var(--menu-icon-separation)}#main-menu li span{flex:1}#main-menu li.current a{color:var(--accent-color);font-weight:700}#main-menu li.menu-bottom-section{margin-top:auto}#main-menu li.menu-bottom-section ol{display:flex;padding-left:0}.menu-social{list-style:none;padding:0;margin:0;display:flex;flex-direction:row;gap:10px}.menu-social svg{width:24px;height:24px;stroke:var(--body-text-color);stroke-width:1.33}.article-list{display:flex;flex-direction:column;gap:var(--section-separation)}.article-list article{display:flex;flex-direction:column;background-color:var(--card-background);box-shadow:var(--shadow-l1);border-radius:var(--card-border-radius);overflow:hidden;transition:box-shadow .3s ease}.article-list article:hover{box-shadow:var(--shadow-l2)}.article-list article .article-image img{width:100%;height:150px;object-fit:cover}@media(min-width:768px){.article-list article .article-image img{height:200px}}@media(min-width:1280px){.article-list article .article-image img{height:250px}}.article-list article:nth-child(5n+1) .article-category a{background:#8ea885;color:#fff}.article-list article:nth-child(5n+2) .article-category a{background:#df7988;color:#fff}.article-list article:nth-child(5n+3) .article-category a{background:#0177b8;color:#fff}.article-list article:nth-child(5n+4) .article-category a{background:#ffb900;color:#fff}.article-list article:nth-child(5n+5) .article-category a{background:#6b69d6;color:#fff}.article-details{display:flex;flex-direction:column;justify-content:center;padding:var(--card-padding);gap:15px}.article-title{font-family:var(--article-font-family);font-weight:600;margin:0;color:var(--card-text-color-main);font-size:2.2rem}@media(min-width:1280px){.article-title{font-size:2.4rem}}.article-title a{color:var(--card-text-color-main)}.article-title a:hover{color:var(--card-text-color-main)}.article-subtitle{font-weight:400;color:var(--card-text-color-secondary);line-height:1.5;margin:0;font-size:1.75rem}@media(min-width:1280px){.article-subtitle{font-size:2rem}}.article-title-wrapper{display:flex;flex-direction:column;gap:8px}.article-time,.article-translations{display:flex;color:var(--card-text-color-tertiary);gap:15px}.article-time svg,.article-translations svg{vertical-align:middle;width:20px;height:20px;stroke-width:1.33;flex-shrink:0}.article-time time,.article-time a,.article-translations time,.article-translations a{font-size:1.4rem;color:var(--card-text-color-tertiary)}.article-time>div,.article-translations>div{display:inline-flex;align-items:center;gap:15px}.article-time{flex-wrap:wrap}.article-translations>div{flex-wrap:wrap}.article-category,.article-tags{display:flex;gap:10px}.article-category a,.article-tags a{color:var(--accent-color-text);background-color:var(--accent-color);padding:8px 16px;border-radius:var(--tag-border-radius);display:inline-block;font-size:1.4rem;transition:background-color .5s ease}.article-category a:hover,.article-tags a:hover{color:var(--accent-color-text);background-color:var(--accent-color-darker)}.article-list--compact{border-radius:var(--card-border-radius);box-shadow:var(--shadow-l1);background-color:var(--card-background);--image-size:50px}@media(min-width:768px){.article-list--compact{--image-size:60px}}.article-list--compact article>a{display:flex;align-items:center;padding:var(--small-card-padding);gap:15px}.article-list--compact article:not(:last-of-type){border-bottom:1.5px solid var(--card-separator-color)}.article-list--compact article .article-details{flex-grow:1;padding:0;min-height:var(--image-size);gap:10px}.article-list--compact article .article-title{margin:0;font-size:1.6rem}@media(min-width:768px){.article-list--compact article .article-title{font-size:1.8rem}}.article-list--compact article .article-image img{width:var(--image-size);height:var(--image-size);object-fit:cover}.article-list--compact article .article-time{font-size:1.4rem}.article-list--compact article .article-preview{font-size:1.4rem;color:var(--card-text-color-tertiary);margin-top:10px;line-height:1.5}.article-list--tile article{border-radius:var(--card-border-radius);overflow:hidden;position:relative;height:350px;width:250px;box-shadow:var(--shadow-l1);transition:box-shadow .3s ease;background-color:var(--card-background)}.article-list--tile article:hover{box-shadow:var(--shadow-l2)}.article-list--tile article.has-image .article-details{background-color:rgba(0,0,0,.25)}.article-list--tile article.has-image .article-title{color:#fff}.article-list--tile article .article-image{position:absolute;top:0;left:0;width:100%;height:100%}.article-list--tile article .article-image img{width:100%;height:100%;object-fit:cover}.article-list--tile article .article-details{border-radius:var(--card-border-radius);position:relative;height:100%;width:100%;display:flex;flex-direction:column;justify-content:flex-end;z-index:2;padding:15px}@media(min-width:640px){.article-list--tile article .article-details{padding:20px}}.article-list--tile article .article-title{font-size:2rem;font-weight:500;color:var(--card-text-color-main)}@media(min-width:640px){.article-list--tile article .article-title{font-size:2.2rem}}.widget{display:flex;flex-direction:column}.widget .widget-icon svg{width:32px;height:32px;stroke-width:1.6;color:var(--body-text-color)}.tagCloud .tagCloud-tags{display:flex;flex-wrap:wrap;gap:10px}.tagCloud .tagCloud-tags a{background:var(--card-background);box-shadow:var(--shadow-l1);border-radius:var(--tag-border-radius);padding:8px 20px;color:var(--card-text-color-main);font-size:1.4rem;transition:box-shadow .3s ease}.tagCloud .tagCloud-tags a:hover{box-shadow:var(--shadow-l2)}.widget.archives .widget-archive--list{border-radius:var(--card-border-radius);box-shadow:var(--shadow-l1);background-color:var(--card-background)}.widget.archives .archives-year:not(:last-of-type){border-bottom:1.5px solid var(--card-separator-color)}.widget.archives .archives-year a{font-size:1.4rem;padding:18px 25px;display:flex}.widget.archives .archives-year a span.year{flex:1;color:var(--card-text-color-main);font-weight:700}.widget.archives .archives-year a span.count{color:var(--card-text-color-tertiary)}footer.site-footer{padding:20px 0 var(--section-separation);font-size:1.4rem;line-height:1.75}footer.site-footer:before{content:"";display:block;height:3px;width:50px;background:var(--body-text-color);margin-bottom:20px}footer.site-footer .copyright{color:var(--accent-color);font-weight:700;margin-bottom:5px}footer.site-footer .powerby{color:var(--body-text-color);font-weight:400;font-size:1.2rem}footer.site-footer .powerby a{color:var(--body-text-color)}.pagination{display:flex;background-color:var(--card-background);box-shadow:var(--shadow-l1);border-radius:var(--card-border-radius);overflow:hidden;flex-wrap:wrap}.pagination .page-link{padding:16px 32px;display:inline-flex;color:var(--card-text-color-secondary)}.pagination .page-link.current{font-weight:700;background-color:var(--card-background-selected);color:var(--card-text-color-main)}@media(min-width:768px){.sidebar.sticky{position:sticky}}.left-sidebar{display:flex;flex-direction:column;flex-shrink:0;align-self:stretch;gap:var(--sidebar-element-separation);max-width:none;width:100%;position:relative;--sidebar-avatar-size:100px;--sidebar-element-separation:20px;--emoji-size:40px;--emoji-font-size:20px}@media(min-width:768px){.left-sidebar{width:auto;padding-top:var(--main-top-padding);padding-bottom:var(--main-top-padding);max-height:100vh}}@media(min-width:1536px){.left-sidebar{--sidebar-avatar-size:120px;--sidebar-element-separation:25px;--emoji-size:40px}}.left-sidebar.sticky{top:0}.left-sidebar.compact{--sidebar-avatar-size:80px;--emoji-size:30px;--emoji-font-size:15px}@media(min-width:1024px){.left-sidebar.compact header{flex-direction:row}}.left-sidebar.compact header .site-meta{gap:5px}.left-sidebar.compact header .site-name{font-size:1.4rem}@media(min-width:1536px){.left-sidebar.compact header .site-name{font-size:1.75rem}}.left-sidebar.compact header .site-description{font-size:1.4rem}.right-sidebar{width:100%;display:none;flex-direction:column;gap:var(--widget-separation)}.right-sidebar.sticky{top:0}@media(min-width:1024px){.right-sidebar{padding-top:var(--main-top-padding);padding-bottom:var(--main-top-padding)}}.sidebar header{z-index:1;transition:box-shadow .5s ease;display:flex;flex-direction:column;gap:var(--sidebar-element-separation)}@media(min-width:768px){.sidebar header{padding:0}}.sidebar header .site-avatar{position:relative;margin:0;width:var(--sidebar-avatar-size);height:var(--sidebar-avatar-size);flex-shrink:0}.sidebar header .site-avatar .site-logo{width:100%;height:100%;border-radius:100%;box-shadow:var(--shadow-l1)}.sidebar header .site-avatar .emoji{position:absolute;width:var(--emoji-size);height:var(--emoji-size);line-height:var(--emoji-size);border-radius:100%;bottom:0;right:0;text-align:center;font-size:var(--emoji-font-size);background-color:var(--card-background);box-shadow:var(--shadow-l2)}.sidebar header .site-meta{display:flex;flex-direction:column;gap:10px;justify-content:center}.sidebar header .site-name{color:var(--accent-color);margin:0;font-size:1.6rem}@media(min-width:1536px){.sidebar header .site-name{font-size:1.8rem}}.sidebar header .site-description{color:var(--body-text-color);font-weight:400;margin:0;font-size:1.4rem}@media(min-width:1536px){.sidebar header .site-description{font-size:1.6rem}}[data-scheme=dark] #dark-mode-toggle{color:var(--accent-color);font-weight:700}[data-scheme=dark] #dark-mode-toggle .icon-tabler-toggle-left{display:none}[data-scheme=dark] #dark-mode-toggle .icon-tabler-toggle-right{display:unset}#dark-mode-toggle{margin-top:auto;color:var(--body-text-color);display:flex;align-items:center;cursor:pointer;gap:var(--menu-icon-separation)}#dark-mode-toggle .icon-tabler-toggle-right{display:none}#i18n-switch{color:var(--body-text-color);display:inline-flex;align-content:center;gap:var(--menu-icon-separation)}#i18n-switch select{border:0;background-color:transparent;color:var(--body-text-color)}#i18n-switch select option{color:var(--card-text-color-main);background-color:var(--card-background)}html{font-size:62.5%;overflow-y:scroll}*{box-sizing:border-box}body{background:var(--body-background);margin:0;font-family:var(--base-font-family);font-size:1.6rem;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{scrollbar-width:auto;scrollbar-color:var(--scrollbar-thumb)transparent}::-webkit-scrollbar{height:auto}::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb)}::-webkit-scrollbar-track{background-color:transparent}.article-page.hide-sidebar-sm .left-sidebar{display:none}@media(min-width:768px){.article-page.hide-sidebar-sm .left-sidebar{display:inherit}}.article-page .main-article{background:var(--card-background);border-radius:var(--card-border-radius);box-shadow:var(--shadow-l1);overflow:hidden}.article-page .main-article .article-header .article-image img{height:auto;width:100%;max-height:50vh;object-fit:cover}.article-page .main-article .article-header .article-details{padding:var(--card-padding);padding-bottom:0}.article-page .main-article .article-content{margin:var(--card-padding)0;color:var(--card-text-color-main)}.article-page .main-article .article-content .footnotes{font-family:var(--base-font-family)}.article-page .main-article .article-content img{max-width:100%;height:auto}.article-page .main-article .article-footer{margin:var(--card-padding);margin-top:0}.article-page .main-article .article-footer section:not(:first-child){margin-top:var(--card-padding)}.article-page .main-article .article-footer section{color:var(--card-text-color-tertiary);text-transform:uppercase;display:flex;align-items:center;font-size:1.4rem;gap:15px}.article-page .main-article .article-footer section svg{width:20px;height:20px;stroke-width:1.33}.article-page .main-article .article-footer .article-tags{flex-wrap:wrap;text-transform:unset}.article-page .main-article .article-footer .article-copyright a,.article-page .main-article .article-footer .article-lastmod a{color:var(--body-text-color)}.article-page .main-article .article-footer .article-copyright a.link,.article-page .main-article .article-footer .article-lastmod a.link{box-shadow:unset}.widget--toc{background-color:var(--card-background);border-radius:var(--card-border-radius);box-shadow:var(--shadow-l1);display:flex;flex-direction:column;color:var(--card-text-color-main);overflow:hidden}.widget--toc ::-webkit-scrollbar-thumb{background-color:var(--card-separator-color)}.widget--toc #TableOfContents{overflow-x:auto;max-height:75vh}.widget--toc #TableOfContents ol,.widget--toc #TableOfContents ul{margin:0;padding:0}.widget--toc #TableOfContents ol{list-style-type:none;counter-reset:item}.widget--toc #TableOfContents ol li a:first-of-type::before{counter-increment:item;content:counters(item,".")". ";font-weight:700;margin-right:5px}.widget--toc #TableOfContents>ul{padding:0 1em}.widget--toc #TableOfContents li{margin:15px 0 15px 20px;padding:5px}.widget--toc #TableOfContents li>ol,.widget--toc #TableOfContents li>ul{margin-top:10px;padding-left:10px;margin-bottom:-5px}.widget--toc #TableOfContents li>ol>li:last-child,.widget--toc #TableOfContents li>ul>li:last-child{margin-bottom:0}.widget--toc #TableOfContents li.active-class>a{border-left:var(--heading-border-size)solid var(--accent-color);font-weight:700}.widget--toc #TableOfContents ul li.active-class>a{display:block}.widget--toc #TableOfContents>ul>li.active-class>a{margin-left:calc(-25px - 1em);padding-left:calc(25px + 1em - var(--heading-border-size))}.widget--toc #TableOfContents>ol>li.active-class>a{margin-left:calc(-9px - 1em);padding-left:calc(9px + 1em - var(--heading-border-size));display:block}.widget--toc #TableOfContents>ul>li>ul>li.active-class>a{margin-left:calc(-60px - 1em);padding-left:calc(60px + 1em - var(--heading-border-size))}.widget--toc #TableOfContents>ol>li>ol>li.active-class>a{margin-left:calc(-44px - 1em);padding-left:calc(44px + 1em - var(--heading-border-size));display:block}.widget--toc #TableOfContents>ul>li>ul>li>ul>li.active-class>a{margin-left:calc(-95px - 1em);padding-left:calc(95px + 1em - var(--heading-border-size))}.widget--toc #TableOfContents>ol>li>ol>li>ol>li.active-class>a{margin-left:calc(-79px - 1em);padding-left:calc(79px + 1em - var(--heading-border-size));display:block}.widget--toc #TableOfContents>ul>li>ul>li>ul>li>ul>li.active-class>a{margin-left:calc(-130px - 1em);padding-left:calc(130px + 1em - var(--heading-border-size))}.widget--toc #TableOfContents>ol>li>ol>li>ol>li>ol>li.active-class>a{margin-left:calc(-114px - 1em);padding-left:calc(114px + 1em - var(--heading-border-size));display:block}.widget--toc #TableOfContents>ul>li>ul>li>ul>li>ul>li>ul>li.active-class>a{margin-left:calc(-165px - 1em);padding-left:calc(165px + 1em - var(--heading-border-size))}.widget--toc #TableOfContents>ol>li>ol>li>ol>li>ol>li>ol>li.active-class>a{margin-left:calc(-149px - 1em);padding-left:calc(149px + 1em - var(--heading-border-size));display:block}.related-content{overflow-x:auto;padding-bottom:15px}.related-content>.flex{float:left}.related-content article{margin-right:15px;flex-shrink:0;overflow:hidden;width:250px;height:150px}.related-content article .article-title{font-size:1.8rem;margin:0}.related-content article.has-image .article-details{padding:20px;background:linear-gradient(0deg,rgba(0,0,0,.25) 0%,rgba(0,0,0,.75) 100%)}.article-content{font-family:var(--article-font-family);font-size:var(--article-font-size);padding:0 var(--card-padding);line-height:var(--article-line-height)}.article-content>p{margin:1.5em 0}.article-content h1,.article-content h2,.article-content h3,.article-content h4,.article-content h5,.article-content h6{margin-inline-start:calc((var(--card-padding)) * -1);padding-inline-start:calc(var(--card-padding) - var(--heading-border-size));border-inline-start:var(--heading-border-size)solid var(--accent-color);position:relative}.article-content h1 a.header-anchor,.article-content h2 a.header-anchor,.article-content h3 a.header-anchor,.article-content h4 a.header-anchor,.article-content h5 a.header-anchor,.article-content h6 a.header-anchor{transition:opacity .3s ease;opacity:0;position:absolute;left:0;width:var(--card-padding);text-align:center;color:var(--accent-color)}.article-content h1 a.header-anchor:before,.article-content h2 a.header-anchor:before,.article-content h3 a.header-anchor:before,.article-content h4 a.header-anchor:before,.article-content h5 a.header-anchor:before,.article-content h6 a.header-anchor:before{content:"#"}.article-content h1:hover a.header-anchor,.article-content h1:focus a.header-anchor,.article-content h2:hover a.header-anchor,.article-content h2:focus a.header-anchor,.article-content h3:hover a.header-anchor,.article-content h3:focus a.header-anchor,.article-content h4:hover a.header-anchor,.article-content h4:focus a.header-anchor,.article-content h5:hover a.header-anchor,.article-content h5:focus a.header-anchor,.article-content h6:hover a.header-anchor,.article-content h6:focus a.header-anchor{opacity:1}.article-content figure{text-align:center}.article-content figure figcaption{font-size:1.4rem;color:var(--card-text-color-secondary)}.article-content blockquote{position:relative;margin:1.5em 0;border-inline-start:var(--blockquote-border-size)solid var(--card-separator-color);padding:15px calc(var(--card-padding) - var(--blockquote-border-size));background-color:var(--blockquote-background-color)}.article-content blockquote .cite{display:block;text-align:right;font-size:.75em}.article-content blockquote .cite a{text-decoration:underline}.article-content hr{width:100px;margin:40px auto;background:var(--card-text-color-tertiary);height:2px;border:0;opacity:.55}.article-content code{color:var(--code-text-color);background-color:var(--code-background-color);padding:2px 4px;border-radius:var(--tag-border-radius);font-family:var(--code-font-family)}.article-content a,.article-content code{word-break:break-word}.article-content .gallery{position:relative;display:flex;flex-direction:row;justify-content:center;margin:1.5em 0;gap:10px}.article-content .gallery figure{margin:0}.article-content pre{overflow-x:auto;display:block;background-color:var(--pre-background-color);color:var(--pre-text-color);font-family:var(--code-font-family);line-height:1.428571429;word-break:break-all;padding:var(--card-padding)}[dir=rtl] .article-content pre{direction:ltr}.article-content pre code{color:unset;border:none;background:0 0;padding:0}.article-content .highlight{background-color:var(--pre-background-color);padding:var(--card-padding);position:relative}.article-content .highlight:hover .copyCodeButton{opacity:1}[dir=rtl] .article-content .highlight{direction:ltr}.article-content .highlight pre{margin:initial;padding:0;margin:0;width:auto}.article-content .copyCodeButton{position:absolute;top:calc(var(--card-padding));right:calc(var(--card-padding));background:var(--card-background);border:none;box-shadow:var(--shadow-l2);border-radius:var(--tag-border-radius);padding:8px 16px;color:var(--card-text-color-main);cursor:pointer;font-size:14px;opacity:0;transition:opacity .3s ease}.article-content .table-wrapper{padding:0 var(--card-padding);overflow-x:auto;display:block}.article-content table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:1.5em;font-size:.96em}.article-content th,.article-content td{text-align:left;padding:4px 8px 4px 10px;border:1px solid var(--table-border-color)}.article-content td{vertical-align:top}.article-content tr:nth-child(even){background-color:var(--tr-even-background-color)}.article-content .twitter-tweet{color:var(--card-text-color-main)}.article-content .video-wrapper{position:relative;width:100%;height:0;padding-bottom:56.25%;overflow:hidden}.article-content .video-wrapper>iframe,.article-content .video-wrapper>video{position:absolute;width:100%;height:100%;left:0;top:0;border:0}.article-content .gitlab-embed-snippets{margin:0!important}.article-content .gitlab-embed-snippets .file-holder.snippet-file-content{margin-block-end:0!important;margin-block-start:0!important;margin-left:calc((var(--card-padding)) * -1)!important;margin-right:calc((var(--card-padding)) * -1)!important;padding:0 var(--card-padding)!important}.article-content blockquote,.article-content figure,.article-content .highlight,.article-content pre,.article-content .gallery,.article-content .video-wrapper,.article-content .table-wrapper,.article-content .s_video_simple{margin-left:calc((var(--card-padding)) * -1);margin-right:calc((var(--card-padding)) * -1);width:calc(100% + var(--card-padding) * 2)}.article-content .katex-display>.katex{overflow-x:auto;overflow-y:hidden}.article-content kbd{border:1px solid var(--kbd-border-color);font-weight:700;font-size:.9em;line-height:1;padding:2px 4px;border-radius:4px;display:inline-block}.section-card{border-radius:var(--card-border-radius);background-color:var(--card-background);padding:var(--small-card-padding);box-shadow:var(--shadow-l1);display:flex;align-items:center;gap:20px;--separation:15px}.section-card .section-term{font-size:2.2rem;margin:0;color:var(--card-text-color-main)}.section-card .section-description{font-weight:400;color:var(--card-text-color-secondary);font-size:1.6rem;margin:0}.section-card .section-details{flex-grow:1;display:flex;flex-direction:column;gap:8px}.section-card .section-image img{width:60px;height:60px}.section-card .section-count{color:var(--card-text-color-tertiary);font-size:1.4rem;margin:0;font-weight:700;text-transform:uppercase}.subsection-list{overflow-x:auto}.subsection-list .article-list--tile{display:flex;padding-bottom:15px}.subsection-list .article-list--tile article{width:250px;height:150px;margin-right:20px;flex-shrink:0}.subsection-list .article-list--tile article .article-title{margin:0;font-size:1.8rem}.subsection-list .article-list--tile article .article-details{padding:20px}.not-found-card{background-color:var(--card-background);box-shadow:var(--shadow-l1);border-radius:var(--card-border-radius);padding:var(--card-padding)}.search-form{position:relative;--button-size:80px}.search-form.widget{--button-size:60px}.search-form.widget label{font-size:1.3rem;top:10px}.search-form.widget input{font-size:1.5rem;padding:30px 20px 15px}.search-form p{position:relative;margin:0}.search-form label{position:absolute;top:15px;inset-inline-start:20px;font-size:1.4rem;color:var(--card-text-color-tertiary)}.search-form input{padding:40px 20px 20px;border-radius:var(--card-border-radius);background-color:var(--card-background);box-shadow:var(--shadow-l1);color:var(--card-text-color-main);width:100%;border:0;-webkit-appearance:none;transition:box-shadow .3s ease;font-size:1.8rem}.search-form input:focus{outline:0;box-shadow:var(--shadow-l2)}.search-form button{position:absolute;inset-inline-end:0;top:0;height:100%;width:var(--button-size);cursor:pointer;background-color:transparent;border:0;padding:0 10px}.search-form button:focus{outline:0}.search-form button:focus svg{stroke-width:2;color:var(--accent-color)}.search-form button svg{color:var(--card-text-color-secondary);stroke-width:1.33;transition:all .3s ease;width:20px;height:20px}a{text-decoration:none;color:var(--accent-color)}a:hover{color:var(--accent-color-darker)}a.link{box-shadow:0 -2px rgba(var(--link-background-color),var(--link-background-opacity))inset;transition:all .3s ease}a.link:hover{box-shadow:0 calc(-1rem * var(--article-line-height))rgba(var(--link-background-color),var(--link-background-opacity-hover))inset}.section-title{text-transform:uppercase;margin-top:0;margin-bottom:10px;display:block;font-size:1.6rem;font-weight:700;color:var(--body-text-color)}.section-title a{color:var(--body-text-color)} \ No newline at end of file diff --git a/search/index.html b/search/index.html new file mode 100644 index 000000000..f6030d0bc --- /dev/null +++ b/search/index.html @@ -0,0 +1,17 @@ +Search +

+

\ No newline at end of file diff --git a/search/index.json b/search/index.json new file mode 100644 index 000000000..333373474 --- /dev/null +++ b/search/index.json @@ -0,0 +1 @@ +[{"content":"瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) 1.准备工作 软件环境:\nRT-Thread 主仓代码(需下载至本地) vscode rt-thread env 硬件环境:\nRA6M3-HMI-Board 开发板 0.96寸 ssd1306 oled 显示屏 2.工程配置 首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:\n1 $ cd rt-thread\\bsp\\renesas\\ra6m3-hmi-board 这里需要我们提前安装好 ENV 环境,具体细节请参考 Env编译环境搭建 。\n鼠标右键打开 ENV 工具后,使用 menuconfig 命令打开可视化菜单,勾选上 RTduino 的使能项,保存并退出\n1 2 3 4 RT-Thread Configuration → Hardware Drivers Config → Onboard Peripheral Drivers [*] Compatible with Arduino Ecosystem (RTduino) 此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):\n1 $ pkgs --update 我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:\n3.开始编译 打开 ENV ,同时执行如下命令:\n1 $ scons -j16 在工程编译完成后会生成一个 .elf后缀的可执行文件,到这里工程的编译就顺利结束了。\n4.vscode调试配置 首先我们需要在 vscode 中安装 Cortex-Debug 插件,打开 vscode 扩展,搜索 Cortex-Debug并安装扩展:\n接下来就是安装 pyocd 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:\n1 download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases 接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 create a launch.json file:\n之后 vscode 会创建一份 launch.json 文件,我们需要替换文件内容为:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 \u0026#34;version\u0026#34;: \u0026#34;0.2.0\u0026#34;, \u0026#34;configurations\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;HMI-Board\u0026#34;, \u0026#34;cwd\u0026#34;: \u0026#34;${workspaceFolder}\u0026#34;, \u0026#34;executable\u0026#34;: \u0026#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf\u0026#34;, \u0026#34;request\u0026#34;: \u0026#34;launch\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;cortex-debug\u0026#34;, \u0026#34;runToEntryPoint\u0026#34;: \u0026#34;main\u0026#34;, \u0026#34;targetId\u0026#34;: \u0026#34;R7FA6M3AH\u0026#34;, \u0026#34;servertype\u0026#34;: \u0026#34;pyocd\u0026#34;, \u0026#34;serverpath\u0026#34;: \u0026#34;D:/compile/sdk-debugger-pyocd/pyocd.bat\u0026#34;, \u0026#34;armToolchainPath\u0026#34;: \u0026#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin\u0026#34;, \u0026#34;gdbPath\u0026#34;: \u0026#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe\u0026#34;, }, ] } 注意:launch.json文件中的部分参数需要根据具体位置配置\nserverpath:这部分路径在前面所安装的 sdk-debugger-pyocd位置 armToolchainPath:gcc 工具链,找不到位置的可以点击此处下载 gdbPath 在完成上述配置后就可以点击 F5 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:\n我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:\n到这里 RTduino 就已经成功运行在 RT-Thread 啦!\n5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled 在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过RTduino,并在RT-Thread中使用 Arduino 源码驱动一个 oled 屏幕。\n我们接着回到 ENV 中,使用 menuconfig命令打开菜单,同时使用 shift + /打开搜索界面,并且输入:ssd1306关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 Adafruit SSD1306对应的 2选项,进入点击 y 使能:\n这样我们就成功把 Adafruit SSD1306 示例库下载到本地了,同时还有一下依赖库:\n我们找到路径:rt-thread\\bsp\\renesas\\ra6m3-hmi-board\\packages\\Adafruit-SSD1306-latest\\examples\\ssd1306_128x64_i2c,可以看到该文件夹下有一个ssd1306_128x64_i2c.ino文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的arduino_main.cpp文件中:\n1 $ cd rt-thread\\bsp\\renesas\\ra6m3-hmi-board\\board\\rtduino\\arduino_main.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-10-28 Wangyuqiang first version */ #include \u0026lt;Arduino.h\u0026gt; #include \u0026lt;SPI.h\u0026gt; #include \u0026lt;Wire.h\u0026gt; #include \u0026lt;Adafruit_GFX.h\u0026gt; #include \u0026lt;Adafruit_SSD1306.h\u0026gt; #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // On an arduino UNO: A4(SDA), A5(SCL) // On an arduino MEGA 2560: 20(SDA), 21(SCL) // On an arduino LEONARDO: 2(SDA), 3(SCL), ... #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C ///\u0026lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, \u0026amp;Wire, OLED_RESET); #define NUMFLAKES 10 // Number of snowflakes in the animation example #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 static const unsigned char PROGMEM logo_bmp[] = { 0b00000000, 0b11000000, 0b00000001, 0b11000000, 0b00000001, 0b11000000, 0b00000011, 0b11100000, 0b11110011, 0b11100000, 0b11111110, 0b11111000, 0b01111110, 0b11111111, 0b00110011, 0b10011111, 0b00011111, 0b11111100, 0b00001101, 0b01110000, 0b00011011, 0b10100000, 0b00111111, 0b11100000, 0b00111111, 0b11110000, 0b01111100, 0b11110000, 0b01110000, 0b01110000, 0b00000000, 0b00110000 }; void testdrawline(); // Draw many lines void testdrawrect(void); // Draw rectangles (outlines) void testfillrect(void); // Draw rectangles (filled) void testdrawcircle(void); // Draw circles (outlines) void testfillcircle(void); // Draw circles (filled) void testdrawroundrect(void); // Draw rounded rectangles (outlines) void testfillroundrect(void); // Draw rounded rectangles (filled) void testdrawtriangle(void); // Draw triangles (outlines) void testfilltriangle(void); // Draw triangles (filled) void testdrawchar(void); // Draw characters of the default font void testdrawstyles(void); // Draw \u0026#39;stylized\u0026#39; characters void testscrolltext(void); // Draw scrolling text void testdrawbitmap(void); // Draw a small bitmap image void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h); void setup() { Serial.begin(115200); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F(\u0026#34;SSD1306 allocation failed\u0026#34;)); for(;;); // Don\u0026#39;t proceed, loop forever } // Show initial display buffer contents on the screen -- // the library initializes this with an Adafruit splash screen. display.display(); delay(2000); // Pause for 2 seconds // Clear the buffer display.clearDisplay(); // Draw a single pixel in white display.drawPixel(10, 10, SSD1306_WHITE); // Show the display buffer on the screen. You MUST call display() after // drawing commands to make them visible on screen! display.display(); delay(2000); // display.display() is NOT necessary after every single drawing command, // unless that\u0026#39;s what you want...rather, you can batch up a bunch of // drawing operations and then update the screen all at once by calling // display.display(). These examples demonstrate both approaches... testdrawline(); // Draw many lines testdrawrect(); // Draw rectangles (outlines) testfillrect(); // Draw rectangles (filled) testdrawcircle(); // Draw circles (outlines) testfillcircle(); // Draw circles (filled) testdrawroundrect(); // Draw rounded rectangles (outlines) testfillroundrect(); // Draw rounded rectangles (filled) testdrawtriangle(); // Draw triangles (outlines) testfilltriangle(); // Draw triangles (filled) testdrawchar(); // Draw characters of the default font testdrawstyles(); // Draw \u0026#39;stylized\u0026#39; characters testscrolltext(); // Draw scrolling text testdrawbitmap(); // Draw a small bitmap image // Invert and restore display, pausing in-between display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps } void loop() { } void testdrawline() { int16_t i; display.clearDisplay(); // Clear display buffer for(i=0; i\u0026lt;display.width(); i+=4) { display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE); display.display(); // Update screen with each newly-drawn line delay(1); } for(i=0; i\u0026lt;display.height(); i+=4) { display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for(i=0; i\u0026lt;display.width(); i+=4) { display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE); display.display(); delay(1); } for(i=display.height()-1; i\u0026gt;=0; i-=4) { display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for(i=display.width()-1; i\u0026gt;=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE); display.display(); delay(1); } for(i=display.height()-1; i\u0026gt;=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for(i=0; i\u0026lt;display.height(); i+=4) { display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE); display.display(); delay(1); } for(i=0; i\u0026lt;display.width(); i+=4) { display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE); display.display(); delay(1); } delay(2000); // Pause for 2 seconds } void testdrawrect(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;display.height()/2; i+=2) { display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE); display.display(); // Update screen with each newly-drawn rectangle delay(1); } delay(2000); } void testfillrect(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;display.height()/2; i+=3) { // The INVERSE color is used so rectangles alternate white/black display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE); display.display(); // Update screen with each newly-drawn rectangle delay(1); } delay(2000); } void testdrawcircle(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;max(display.width(),display.height())/2; i+=2) { display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE); display.display(); delay(1); } delay(2000); } void testfillcircle(void) { display.clearDisplay(); for(int16_t i=max(display.width(),display.height())/2; i\u0026gt;0; i-=3) { // The INVERSE color is used so circles alternate white/black display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE); display.display(); // Update screen with each newly-drawn circle delay(1); } delay(2000); } void testdrawroundrect(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;display.height()/2-2; i+=2) { display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, SSD1306_WHITE); display.display(); delay(1); } delay(2000); } void testfillroundrect(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;display.height()/2-2; i+=2) { // The INVERSE color is used so round-rects alternate white/black display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, SSD1306_INVERSE); display.display(); delay(1); } delay(2000); } void testdrawtriangle(void) { display.clearDisplay(); for(int16_t i=0; i\u0026lt;max(display.width(),display.height())/2; i+=5) { display.drawTriangle( display.width()/2 , display.height()/2-i, display.width()/2-i, display.height()/2+i, display.width()/2+i, display.height()/2+i, SSD1306_WHITE); display.display(); delay(1); } delay(2000); } void testfilltriangle(void) { display.clearDisplay(); for(int16_t i=max(display.width(),display.height())/2; i\u0026gt;0; i-=5) { // The INVERSE color is used so triangles alternate white/black display.fillTriangle( display.width()/2 , display.height()/2-i, display.width()/2-i, display.height()/2+i, display.width()/2+i, display.height()/2+i, SSD1306_INVERSE); display.display(); delay(1); } delay(2000); } void testdrawchar(void) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char \u0026#39;Code Page 437\u0026#39; font // Not all the characters will fit on the display. This is normal. // Library will draw what it can and the rest will be clipped. for(int16_t i=0; i\u0026lt;256; i++) { if(i == \u0026#39;\\n\u0026#39;) display.write(\u0026#39; \u0026#39;); else display.write(i); } display.display(); delay(2000); } void testdrawstyles(void) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.println(F(\u0026#34;Hello, world!\u0026#34;)); display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw \u0026#39;inverse\u0026#39; text display.println(3.141592); display.setTextSize(2); // Draw 2X-scale text display.setTextColor(SSD1306_WHITE); display.print(F(\u0026#34;0x\u0026#34;)); display.println(0xDEADBEEF, HEX); display.display(); delay(2000); } void testscrolltext(void) { display.clearDisplay(); display.setTextSize(2); // Draw 2X-scale text display.setTextColor(SSD1306_WHITE); display.setCursor(10, 0); display.println(F(\u0026#34;scroll\u0026#34;)); display.display(); // Show initial text delay(100); // Scroll in various directions, pausing in-between: display.startscrollright(0x00, 0x0F); delay(2000); display.stopscroll(); delay(1000); display.startscrollleft(0x00, 0x0F); delay(2000); display.stopscroll(); delay(1000); display.startscrolldiagright(0x00, 0x07); delay(2000); display.startscrolldiagleft(0x00, 0x07); delay(2000); display.stopscroll(); delay(1000); } void testdrawbitmap(void) { display.clearDisplay(); display.drawBitmap( (display.width() - LOGO_WIDTH ) / 2, (display.height() - LOGO_HEIGHT) / 2, logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1); display.display(); delay(1000); } #define XPOS 0 // Indexes into the \u0026#39;icons\u0026#39; array in function below #define YPOS 1 #define DELTAY 2 void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) { int8_t f, icons[NUMFLAKES][3]; // Initialize \u0026#39;snowflake\u0026#39; positions for(f=0; f\u0026lt; NUMFLAKES; f++) { icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); icons[f][YPOS] = -LOGO_HEIGHT; icons[f][DELTAY] = random(1, 6); Serial.print(F(\u0026#34;x: \u0026#34;)); Serial.print(icons[f][XPOS], DEC); Serial.print(F(\u0026#34; y: \u0026#34;)); Serial.print(icons[f][YPOS], DEC); Serial.print(F(\u0026#34; dy: \u0026#34;)); Serial.println(icons[f][DELTAY], DEC); } for(;;) { // Loop forever... display.clearDisplay(); // Clear the display buffer // Draw each snowflake: for(f=0; f\u0026lt; NUMFLAKES; f++) { display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE); } display.display(); // Show the display buffer on the screen delay(200); // Pause for 1/10 second // Then update coordinates of each flake... for(f=0; f\u0026lt; NUMFLAKES; f++) { icons[f][YPOS] += icons[f][DELTAY]; // If snowflake is off the bottom of the screen... if (icons[f][YPOS] \u0026gt;= display.height()) { // Reinitialize to a random position, just off the top icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); icons[f][YPOS] = -LOGO_HEIGHT; icons[f][DELTAY] = random(1, 6); } } } } 在此示例中有几点注意事项:\n在每一份添加的示例工程中,我们都必须要包含头文件 #include \u0026lt;Arduino.h\u0026gt; 由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 0x3c,所以对应示例工程中的 SCREEN_ADDRESS需要修改为 0X3C 由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍 接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:\npin func P203 i2c0-sda P202 i2c0-scl VCC vcc GND gnd 接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程\n查看demo:\n","date":"2024-02-18T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover_huad573e2fc4349244e3deecf9a37a5301_121524_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/","title":"【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino"},{"content":"Linux下配置 在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:\n步骤 1: 安装 zsh 确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:\n1 sudo apt-get install zsh 步骤 2: 安装 oh-my-zsh 在终端中运行以下命令来安装 oh-my-zsh:\n1 sh -c \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\u0026#34; 或者,如果你没有安装 curl,可以使用 wget:\n1 sh -c \u0026#34;$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)\u0026#34; 步骤 3: 更改主题 打开 ~/.zshrc 文件以编辑它:\n1 nano ~/.zshrc 找到 ZSH_THEME 行并更改主题。你可以在 oh-my-zsh 主题库中选择一个主题,例如:\n1 ZSH_THEME=\u0026#34;agnoster\u0026#34; 保存并关闭文件。\n步骤 4: 启用历史回溯 oh-my-zsh 默认启用历史回溯。确保 ~/.zshrc 中没有明确禁用该功能的设置。检查是否存在以下行:\n1 HIST_STAMPS=\u0026#34;yyyy-mm-dd\u0026#34; 这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:\n1 HIST_STAMPS=\u0026#34;\u0026#34; 步骤 5: 重新启动 zsh 或打开新终端 在更改 ~/.zshrc 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。\n1 source ~/.zshrc 现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 zsh 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。\nWindwos下配置 在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 PSReadLine 模块,它提供了丰富的命令行编辑和历史记录功能。\n以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:\n安装 PSReadLine 模块: 打开 PowerShell 终端,并执行以下命令来安装 PSReadLine 模块:\n1 Install-Module -Name PSReadLine -Force -SkipPublisherCheck 配置 PowerShell 用户配置文件: 执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):\n1 notepad $PROFILE 在配置文件中添加以下行: 在打开的配置文件中,添加以下内容:\n1 2 3 4 Import-Module PSReadLine Set-PSReadLineOption -HistoryNoDuplicates:$false Set-PSReadLineOption -EditMode Emacs 保存并关闭文件。\n重新启动 PowerShell: 关闭当前的 PowerShell 终端,并重新打开一个新的终端。\n使用历史记录搜索: 可以在 PowerShell 终端中使用 Ctrl + r 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。\n","date":"2024-02-03T15:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/cover_hu6cc81a9902269324bd2156ee8382941d_21092_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/","title":"【经验分享】如何让你的终端实现自动补齐、历史回溯"},{"content":"MPU与MCU MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。\n但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。\n在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。\n由于主要完成“控制”相关的任务,所以称为 Controller。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。\n而Processor,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。\n以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。\n为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。\n从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。\n总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。\n","date":"2023-11-04T00:00:00Z","image":"https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/","title":"【嵌入式素养提升】MPU与MCU"},{"content":"快速上手micro ros \u0026amp;\u0026amp; RT-Thread(serial和udp方式) 1.背景介绍 Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。\nMicro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。\nmicro ros分层模块架构 以下是Micro-ROS的一些关键特点和概念:\n嵌入式系统支持: Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。\n实时性和硬件抽象: Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。\n通信和中间件: Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。\n适用于机器人和自动化: Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。\n可扩展性: Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。\n开源: Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。\n本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。\n2.工程准备工作 2.1 克隆 RT-Thread主仓 1 $ git clone https://github.com/RT-Thread/rt-thread.git 2.2 克隆 env-windows 1 $ git clone --recursive --depth 1 https://github.com/RT-Thread/env-windows.git 克隆下来的 env-windows 可以放在D盘,同时双击打开 env.exe,待启动ConEmu终端后将其注册到鼠标右键快捷方式\n3.编译准备工作 3.1 python \u0026amp; cmake安装 首先去官网安装如下工具:\npython(大于python36):https://www.python.org/downloads/windows/ cmake(大于v3.22):https://cmake.org/files/ 3.2 scons工具安装 打开 windows powershell ,使用 python 安装 scons\n1 $ pip3 install scons 3.3 GNU make安装 GNU make 的安装可以参考该 issue 的三种方式\nhttps://github.com/kurisaW/micro_ros_rtthread_component/issues/5 这里我选择的是使用choco安装make,打开windows powershell(管理员):\n1 2 $ Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString(\u0026#39;https://chocolatey.org/install.ps1\u0026#39;)) $ choco install make 3.4 Fastgithub安装 为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub\nhttps://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip 4.工程配置 选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark\n1 $ cd .\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark 4.1 指定工具链 去官网下载 gcc-arm-none-eabi-10-2020-q4-major-win32工具链,注意不用配置到环境变量中,以免发生冲突\ngcc-arm-none-eabi-10-2020-q4-major-win32.exe 修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链\n4.2 micro_ros 软件包配置 回到.\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark目录下,打开 ConEmu 执行如下命令生成 packages 目录\n1 2 $ pkgs --update $ cd packages 克隆 micro_ros 配置仓库\n1 $ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git 我们来看下目录层次:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ├─micro_ros_rtthread_component │ ├─.images │ ├─builder │ │ ├─extra_packages │ │ ├─metas │ │ ├─microros_utils │ │ └─patchs │ │ ├─foxy │ │ └─humble │ ├─docs │ ├─examples │ ├─include │ ├─package │ │ └─micro_ros_rtthread_package │ └─src 这里我们需要将micro_ros_rtthread_package目录复制一份到..\\env-windows\\packages目录下,同时修改..\\env-windows\\packages\\Kconfig内容如下:\n1 2 source \u0026#34;$PKGS_DIR/packages/Kconfig\u0026#34; source \u0026#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig\u0026#34; 4.3 指定Cmake编译工具链 想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 libmicroros.a静态链接库文件,下面是 micro_ros Cmake 的相关配置:\n回到目录:..\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark\n使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:\n1 $ scons --target=cmake 此时我们在当前目录下就可以看见一个 CMakeLists.txt文件了,同时我们进入目录.\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark\\packages\\micro_ros_rtthread_component\\builder,找到toolchain.cmake文件,参考前面生成的CMakeLists.txt文件修改toolchain.cmake\n4.4 micro ros 在 ENV 中的配置 再次回到..\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark目录下,打开 ENV 勾选配置:\n1 2 3 4 5 [*] micro-ROS package for RTThread [*] Include examples Distribution (Foxy) ---\u0026gt; Memory configuration ---\u0026gt; ROS node communication mode (serial) ---\u0026gt; 其中在Memory configuration中的Publishers和Subscribers这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 serial\n此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!\n同时我们使用 vscode 打开文件packages\\micro_ros_rtthread_component\\src\\rtt_serial_transport.c,搜索宏MICRO_ROS_SERIAL_NAME并修改为你新创建的串口设备名。\n5.开始编译 回到.\\rt-thread\\bsp\\stm32\\stm32f407-rt-spark目录下,鼠标右键打开 windows powershell ,输入如下命令:\n1 scons --build_microros 此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 C:\\Users\\$user\\AppData\\Local\\Temp\\micro下\n这里的配置项主要位于packages\\micro_ros_rtthread_component\\builder\\SConscript文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在packages\\micro_ros_rtthread_component\\builder\\microros_utils\\repositories.py文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布\n编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 packages\\micro_ros_rtthread_component\\builder\\libmicroros\\libmicroros.a文件,同时将C:\\Users\\20537\\AppData\\Local\\Temp\\micro\\mcu\\install\\include目录复制到packages\\micro_ros_rtthread_component\\builder\\libmicroros\\include目录下\n编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上\n附:这里说下 GCC-AR 是什么:GCC-AR 是 gcc配套的库管理工具,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。\n6.WSL安装及 usbipd 支持 WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述\nDocker安装:打开 wsl 终端,使用官网脚本一键安装即可\n1 2 $ curl -fsSL https://test.docker.com -o test-docker.sh $ sudo sh test-docker.sh usbipd支持 请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html\n7.serial测试 此处仅给出相关命令,具体流程请参考演示视频:\n1 2 3 4 5 6 7 8 9 # windows powershell端 $ usbipd wsl list\t// 查看系统USB设备列表 $ usbipd wsl attach --hardware-id \u0026#34;usb-id\u0026#34;\t// 连接usb至wsl # wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04) $ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0\t// 运行docker microros:foxy代理 $ ros2 topic list\t// 查看ros topic列表 $ ros2 topic echo /micro_ros_rtt_subscriber\t// 打印话题详情 $ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:\\ 10\t// 发布topic data值为10 演示视频:[点击此处精准空降: microros_rtt_serial]\n8.udp4测试 8.1 准备工作 首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**鱼香大佬的网站**\n注意:我们安装的ros版本为 ros:foxy\n继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # 激活ros:foxy环境 $ source /opt/ros/foxy/setup.bash # 创建工作区并拉取micro_ros_setup仓库 $ mkdir /home/$user/microros_ws \u0026amp;\u0026amp; cd /home/$user/microros_ws $ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup # 更新rosdep $ sudo apt update $ export ROSDISTRO_INDEX_URL=https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml $ rosdep update --include-eol-distros $ rosdep install --from-paths src --ignore-src -y $ sudo apt-get install python3-pip # colcon编译 $ colcon build $ source install/local_setup.bash ps:如果提示找不到colcon命令,使用如下方式安装colcon sudo apt install python3-colcon-common-externsions # linux python3 -m pip install colcon-common-externsions # macos pip install -U colcon-commmon-externsions # windows # 创建一份固件工作区 $ ros2 run micro_ros_setup create_firmware_ws.sh host # 构建固件 $ ros2 run micro_ros_setup build_firmware.sh $ source install/local_setup.bash # 创建microros代理 $ ros2 run micro_ros_setup create_agent_ws.sh # 构建代理 $ ros2 run micro_ros_setup build_agent.sh $ source install/local_setup.bash 完成上述工作后我们micro ros的代理环境就准备就绪了\n8.2 以 UDP 方式开启micro_ros 代理 1 $ ros2 run micro_ros_agent micro_ros_agent udp4 --port 9999 8.3 udp测试流程 这里就不讲详细的配置了,具体过程请看下方链接:\n演示视频:[点击此处精准空降: microros_rtt_serial]\n9.几点说明 为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本\n如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务\n如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:\n1 2 3 4 5 # 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令 $ New-NetFirewallRule -DisplayName \u0026#34;WSL\u0026#34; -Direction Inbound -InterfaceAlias \u0026#34;vEthernet (WSL)\u0026#34; -Action Allow # 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令 $ New-NetFirewallRule -DisplayName \u0026#34;WSL\u0026#34; -Direction Outbound -InterfaceAlias \u0026#34;vEthernet (WSL)\u0026#34; -Action Allow 如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境\n具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配\n","date":"2023-10-26T00:00:00Z","image":"https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/","title":"【Micro_ROS】在RT-Thread上运行micro_ros"},{"content":"具体步骤: 首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:\n下载链接:https://github.com/dorssel/usbipd-win/releases\n同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:\n1 $ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool 打开wsl ubuntu终端使用命令:uname -r得到版本号,同时根据版本号使用管理员模式新建目录\n1 $ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases\n这里的版本就是你使用命令 uname -r 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下\n然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):\n1 2 3 4 $ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ $ cd /usr/src/5.15.90.1-microsoft-standard-WSL2/ $ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ \u0026amp;\u0026amp; sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 然后将内核的一些配置信息复制到当前文件夹下:\n1 2 3 $ sudo cp /proc/config.gz config.gz $ sudo gunzip config.gz $ sudo mv config .config 接着我们执行menuconfig命令打开图形化菜单\n1 $ sudo make menuconfig 进入如下路径:\u0026gt; Device Drivers \u0026gt; USB support\n下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:\n1 2 3 4 5 6 7 Device Drivers -\u0026gt; USB Support Device Drivers -\u0026gt; USB Support -\u0026gt; USB announce new devices Device Drivers -\u0026gt; USB Support -\u0026gt; USB Modem (CDC ACM) support Device Drivers -\u0026gt; USB Support -\u0026gt; USB/IP Device Drivers -\u0026gt; USB Support -\u0026gt; USB/IP -\u0026gt; VHCI HCD Device Drivers -\u0026gt; USB Serial Converter Support Device Drivers -\u0026gt; USB Serial Converter Support -\u0026gt; USB FTDI Single port Serial Driver 同时记得关闭 Device Drivers -\u0026gt; USB Support -\u0026gt; USB/IP -\u0026gt; Debug messages for USB/IP这一选项,否则调试信息会非常影响你的使用体验\n另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译\n1 $ sudo make -j8 内核编译期间发生报错:\n这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:\n1 2 3 $ sudo apt install dwarves $ sudo make -j8 \u0026amp;\u0026amp; sudo make modules_install -j8 \u0026amp;\u0026amp; sudo make install -j8 发现又产生了报错:\n查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题\n1 2 3 $ sudo vi .config # 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n` 安装内核时发生报错:\n解决方式有两种:\n1.可以选择在.config中禁用宏CONFIG_X86_X32 2.找到合适的binutils版本使其能够编译 我选择的是第一种,根据我在网上找到的说法是:\n1 2 3 # 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。 # 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。 所以我选择禁用宏CONFIG_X86_X32,之后继续执行命令:\n1 2 $ sudo make modules_install -j8 $ sudo make install -j8 之后就可以选择编译 USBIP 工具了:\n1 2 3 4 $ cd tools/usb/usbip $ sudo ./autogen.sh $ sudo ./configure $ sudo make install -j8 复制工具库位置,以便 usbip 工具可以获取到:\n1 $ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 安装 usb.ids 以便显示 USB 设备的名称:\n1 $ sudo apt-get install hwdata 重启WSL:\n1 $ wsl --shutdown 下面进行测试是否成功: 打开powershell:\n1 $ usbipd wsl list 假设我们需要在wsl使用的 usb 设备为 ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3),设备id为 0483:374b\n我们使用命令附加设备到 wsl2 中\n1 $ usbipd wsl attach --hardware-id \u0026#34;0483:374b\u0026#34; 此时我们打开一个 wsl 终端,使用命令 lsusb 即可看到附加到 wsl 的设备\n然后我们再次回到 powershell ,执行 usbipd wsl list命令,可以看到此时的 usb 设备已经成功添加到 wsl 了\n","date":"2023-10-26T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover_hua939fa00c4e9286056c5c99bbb532251_65046_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/","title":"【经验分享】WSL中使用USB设备"},{"content":"前言 在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑.bashrc文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。\n步骤一:进入home目录 首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:\n1 cd ~ 步骤二:编辑.bashrc文件 接下来,我们需要编辑.bashrc文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:\n1 vi .bashrc 步骤三:添加代码到文件末尾 在打开的.bashrc文件中,将以下代码添加到文件的末尾:\n1 2 3 4 5 6 7 8 9 10 11 function git_branch { branch=\u0026#34;`git branch 2\u0026gt;/dev/null | grep \u0026#34;^\\*\u0026#34; | sed -e \u0026#34;s/^\\*\\ //\u0026#34;`\u0026#34; if [ \u0026#34;${branch}\u0026#34; != \u0026#34;\u0026#34; ];then if [ \u0026#34;${branch}\u0026#34; = \u0026#34;(no branch)\u0026#34; ];then branch=\u0026#34;(`git rev-parse --short HEAD`...)\u0026#34; fi echo \u0026#34; ($branch)\u0026#34; fi } export PS1=\u0026#39;\\u@\\h \\[\\033[01;36m\\]\\W\\[\\033[01;32m\\]$(git_branch)\\[\\033[00m\\] \\$ \u0026#39; 这段代码定义了一个名为git_branch的函数,用于获取并显示当前Git分支的名称。然后,通过export命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。\n步骤四:保存并退出vi编辑器 完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:\n1 :wq 步骤五:执行命令使配置生效 最后,执行以下命令来使新的配置生效:\n1 source ./.bashrc 现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。\n通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!\n","date":"2023-10-09T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_564138_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/","title":"【Git版本控制】在Linux终端显示Git版本信息"},{"content":"1.vmware tools 灰色无法点击 执行如下步骤:\n1 2 3 4 5 sudo apt-get update sudo apt-get upgrade sudo apt-get install open-vm-tools-desktop -y 2.linux安装搜狗输入法 终端安装 fcitx\n1 sudo apt-get install fcitx 到搜狗官方下载 deb 包:\nhttps://shurufa.sogou.com/linux 使用linux自带的安装程序安装输入法后,安装如下输入法依赖:\n1 2 sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 sudo apt install libgsettings-qt1 重启即可\n3.Cmake安装指定版本 首先去官网下载所需版本的压缩包:\nhttps://cmake.org/files/ 执行解压命令\n1 tar -zxv -f cmake-3.22.6.tar.gz 安装相关依赖:\n1 2 3 4 5 sudo apt-get install g++ sudo apt-get install libssl-dev sudo apt-get install make 进入解压后的cmake文件,执行:\n1 ./bootstrap 编译构建:\n1 make 安装:\n1 sudo make install 4.ubuntu中使用 st-link 安装依赖项:\n1 sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc 依次执行如下步骤:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # download source code git clone https://github.com/stlink-org/stlink cd stlink # build cmake . make # install cd bin sudo cp st-* /usr/local/bin cd ../lib sudo cp *.so* /lib32 # add rules sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ sudo udevadm control --reload-rules sudo udevadm trigger 尝试烧录代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #check if st-link is plugged sudo st-info --probe # write hex sudo st-flash --format ihex write myapp.hex # 一般下载一次,会失败,需要刷入两次; # write bin sudo st-flash write in.bin 0x8000000 #stm32f4xx # read bin st-flash read out.bin 0x8000000 0x1000 # restart # 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作 sudo st-flash reset 具体的GDB调试可以参考这篇文章:\nhttps://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html ","date":"2023-10-09T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_2292401_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/","title":"【Linux系统开发】Linux常见开发汇总"},{"content":"前言 最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下\n本地生成公私密钥 首先确保把之前的 ssh 信息清除,也可以将整个 ~/.ssh 目录删除\n1 rm -rf ~/.ssh/* 我们分别生成 Github 和 Gitlab账号的 SSH 密钥\nGithub 生成密钥 1 ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa Gitlab 生成密钥 1 ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa 注意不要选择其他操作,一路回车即可\n此时打开 ~/.ssh/ 目录可以看到生成了四个文件:github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub\n其中 .pub 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存\n远程仓库 SSH 填写公钥密钥 我们先打开 Github 的 Settings选项,然后选择 SSH and GPG keys-\u0026gt;New SSH key ,Title可以随意拟定,Key需要查看刚刚的 github_id-rsa.pub 文件,并且复制到 Gitlab 的key一栏中;\nGitlab 的操作方式与 Github 类似,具体步骤:\n打开 Gitlab -\u0026gt; 用户设置 -\u0026gt; SSH密钥 ,在密钥一栏填入 gitlab_id-rsa.pub文件中的具体值,标题自拟即可。\n配置不同 Host 的 SSH Key 回到 ~/.ssh/ 目录下,并且创建一个名为 config 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:\n1 2 3 4 5 6 7 8 9 10 11 12 #github Host github.com Hostname ssh.github.com Port 443 User git IdentityFile ~/.ssh/github_id-rsa #gitlab host git.rt-thread.com Hostname git.rt-thread.com User git IdentityFile ~/.ssh/gitlab_id-rsa 验证 使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置\nGithub SSH 验证 1 ssh -T git@github.com Gitlab SSH 验证 1 ssh -T git@rt-thread.com 如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功\n","date":"2023-09-16T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover_hubc1531b1b0ec6c2ff6870b01364be3e6_73317_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/","title":"【Git版本控制】Github和Gitlab同时使用ssh"},{"content":"CHIP设备层设计笔记 本文档包含与 CHIP 设备层 ( src/platform) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。\n这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。\n本文档包含以下部分:\n设备层适配模式 设备层适配模式 设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。\nCHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。\n作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。\n为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。\n尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。\n以下各节描述了用于实现这些目标的一些模式。\n接口和实现类 方法转发 目标平台选择 通用实现类 覆盖通用行为 通用实现的多重继承和子类化 通用实现行为的静态虚拟化 .cpp 文件和显式模板实例化 接口和实现类 CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。\n外部可见的抽象接口类定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。\n实现类提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。\n设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。\n抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀Impl。在所有情况下,实现类都需要从其接口类公开继承。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class ConfigurationManagerImpl; /** Interface class for ConfigurationManager component */ class ConfigurationManager { using ImplClass = ConfigurationManagerImpl; public: CHIP_ERROR GetDeviceId(uint64_t \u0026amp; deviceId); static CHIP_ERROR Init(); ... }; /** Concrete implementation of ConfigurationManager component for a specific platform */ class ConfigurationManagerImpl final : public ConfigurationManager { ... }; 方法转发 接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。this这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ 奇怪的重复模板模式 ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,ImplClass使转发方法定义更加简洁。\n1 2 3 4 5 inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t \u0026amp; deviceId) { /* forward method call... */ return static_cast\u0026lt;ImplClass*\u0026gt;(this)-\u0026gt;_GetDeviceId(deviceId); } 该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:\n1 2 3 4 inline CHIP_ERROR ConfigurationManager::Init() { return ImplClass::_Init(); } 作为转发方法目标的实现类上的方法称为*实现方法*。每一种转发方法都必须有相应的实现方法。\n前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。\n实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class ConfigurationManagerImpl; /** Interface class for ConfigurationManager component */ class ConfigurationManager { using ImplClass = ConfigurationManagerImpl; public: CHIP_ERROR GetDeviceId(uint64_t \u0026amp; deviceId); static CHIP_ERROR Init(); ... }; /** Concrete implementation of ConfigurationManager component for specific platform */ class ConfigurationManagerImpl final : public ConfigurationManager { /* Let the forwarding methods on ConfigurationManager call implementation methods on this class. */ friend ConfigurationManager; private: CHIP_ERROR _GetDeviceId(uint64_t \u0026amp; deviceId); static CHIP_ERROR _Init(); ... }; inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t \u0026amp; deviceId) { /* Forward calls to corresponding implementation method... */ return static_cast\u0026lt;ImplClass*\u0026gt;(this)-\u0026gt;_GetDeviceId(deviceId); } inline CHIP_ERROR ConfigurationManager::Init() { /* Forward calls to corresponding static implementation method... */ return ImplClass::_Init(); } 目标平台选择 实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:\n1 2 3 4 5 6 7 8 9 /* contents of ConfigurationManager.h */ ... #define CONFIGURATIONMANAGERIMPL_HEADER \\ \u0026lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h\u0026gt; #include CONFIGURATIONMANAGERIMPL_HEADER ... 该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。\n每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如ESP32)。所有此类文件都具有相同的文件名(例如ConfigurationManagerImpl.h),并且每个文件都包含类似名称的类的定义(ConfigurationManagerImpl)。\n特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 src/adaptations/device-layer/ESP32)。与特定于平台的头目录一样,这些子目录以目标平台命名。\n设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 --device-layer=\u0026lt;target-platform\u0026gt;。传递 \u0026ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:\n1 2 #define CHIP_DEVICE_LAYER_TARGET ESP32 #define CHIP_DEVICE_LAYER_TARGET_ESP32 1 \u0026ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。\n通用实现类 通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。\n为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。\n通用实现基类被实现为遵循 C++ 奇怪重复模板模式的C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /** Generic base class for use in implementing ConfigurationManager components */ template\u0026lt;class ImplClass\u0026gt; class GenericConfigurationManagerImpl { ... }; /** Concrete implementation of ConfigurationManager component for specific platform */ class ConfigurationManagerImpl final : public ConfigurationManager, public GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; /* \u0026lt;-- Implementation provided by generic base class. */ { ... }; 在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /** Interface class for ConfigurationManager component */ class ConfigurationManager { using ImplClass = ConfigurationManagerImpl; public: CHIP_ERROR GetDeviceId(uint64_t \u0026amp; deviceId); static CHIP_ERROR Init(); ... }; /** Generic base class for use in implementing ConfigurationManager components */ template\u0026lt;class ImplClass\u0026gt; class GenericConfigurationManagerImpl { protected: CHIP_ERROR _GetDeviceId(uint64_t \u0026amp; deviceId); /* \u0026lt;-- Invoked when GetDeviceId() called. */ ... }; /** Concrete implementation of ConfigurationManager component for specific platform */ class ConfigurationManagerImpl final : public ConfigurationManager, public GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; { ... }; 覆盖通用行为 如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。\n新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t \u0026amp; deviceId) { using GenericImpl = GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt;; /* Call the generic implementation to get the device id. */ uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); /* Special case the situation where the device id is not known. */ if (deviceId == kNodeIdNotSpecified) { deviceId = PLATFORM_DEFAULT_DEVICE_ID; } return deviceId; } 通用实现的多重继承和子类化 具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。\n1 2 3 4 5 6 7 8 9 /** Concrete implementation of ConfigurationManager component for specific platform */ class ConfigurationManagerImpl final : public ConfigurationManager, public GenericWiFiConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt;, /* \u0026lt;-- WiFi features */ public GenericThreadConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; /* \u0026lt;-- Thread features */ { ... }; 通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /** Generic base class for use in implementing PlatformManager features * on all platforms. */ template\u0026lt;class ImplClass\u0026gt; class GenericPlatformManagerImpl { ... }; /** Generic base class for use in implementing PlatformManager features * on FreeRTOS platforms. */ template\u0026lt;class ImplClass\u0026gt; class GenericPlatformManagerImpl_FreeRTOS : public GenericPlatformManagerImpl\u0026lt;ImplClass\u0026gt; { ... }; 通用实现行为的静态虚拟化 在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。\n例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过GetDeviceId()从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。\nthis遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数Impl()有助于使代码简洁。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 template\u0026lt;class ImplClass\u0026gt; class GenericConfigurationManagerImpl { protected: CHIP_ERROR _GetDeviceId(uint64_t \u0026amp; deviceId); ... private: ImplClass * Impl() { return static_cast\u0026lt;ImplClass*\u0026gt;(this); } }; class ConfigurationManagerImpl final : public ConfigurationManager, public GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; { friend GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt;; private: CHIP_ERROR ReadConfigValue(const char * key, uint64_t \u0026amp; value); }; template\u0026lt;class ImplClass\u0026gt; CHIP_ERROR GenericConfigurationManagerImpl\u0026lt;ImplClass\u0026gt;::_GetDeviceId(uint64_t \u0026amp; deviceId) { /* delegate to the implementation class to read the \u0026#39;device-id\u0026#39; config value */ return Impl()-\u0026gt;ReadConfigValue(“device-id”, deviceId); } CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(const char * key, uint64_t \u0026amp; value) { /* read value from platform-specific key-value store */ ... } 在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。\n同样,委托是通过转换this指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 template\u0026lt;class ImplClass\u0026gt; class GenericPlatformManagerImpl { protected: void _DispatchEvent(const CHIPDeviceEvent * event); void DispatchEventToApplication(const CHIPDeviceEvent * event); ... private: ImplClass * Impl() { return static_cast\u0026lt;ImplClass*\u0026gt;(this); } }; template\u0026lt;class ImplClass\u0026gt; void GenericPlatformManagerImpl\u0026lt;ImplClass\u0026gt;::_DispatchEvent(const CHIPDeviceEvent * event) { ... /* Delegate work to method that can be overridden by implementation class */ Impl()-\u0026gt;DispatchEventToApplication(event); ... } template\u0026lt;class ImplClass\u0026gt; void GenericPlatformManagerImpl\u0026lt;ImplClass\u0026gt;::DispatchEventToApplication(const CHIPDeviceEvent * event) { /* provide default implementation of DispatchEventToApplication() */ ... } .cpp 文件和显式模板实例化 C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。\n为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀.cpp。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。\n1 2 3 4 5 6 7 8 9 /* contents of GenericConfigurationManagerImpl.h */ template\u0026lt;class ImplClass\u0026gt; class GenericConfigurationManagerImpl { protected: CHIP_ERROR _GetDeviceId(uint64_t \u0026amp; deviceId); ... }; 1 2 3 4 5 6 7 /* contents of GenericConfigurationManagerImpl.cpp */ template\u0026lt;class ImplClass\u0026gt; CHIP_ERROR GenericConfigurationManagerImpl\u0026lt;ImplClass\u0026gt;::_GetDeviceId(uint64_t \u0026amp; deviceId) { ... } 通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。为了避免这种情况,设备层使用显式模板实例化的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件extern template class在使用模板类之前都包含一个声明。这告诉编译器不要在该上下文中实例化模板。\n1 2 3 4 5 6 7 8 9 /* contents of ConfigurationManagerImpl.h */ #include \u0026lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h\u0026gt; // Instruct the compiler to instantiate the GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; // class only when explicitly asked to do so. extern template class GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt;; ... 然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并template class使用定义来强制显式实例化模板。\n1 2 3 4 5 6 7 8 /* contents of ConfigurationManagerImpl.cpp */ #include \u0026lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp\u0026gt; // Fully instantiate the GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt; class. template class GenericConfigurationManagerImpl\u0026lt;ConfigurationManagerImpl\u0026gt;; ... 结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。\n","date":"2023-08-20T00:00:00Z","image":"https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover_hu469f982a08585212a410fea8179642b3_154073_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/","title":"【Matter】CHIP设备层设计笔记"},{"content":"如何在Linux平台下测试Matter应用级通信(虚拟设备) 准备工作 1. 递归克隆Matter仓库 执行如下命令:\n1 git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git 如果克隆过程中发生报错,请执行如下命令来同步子模块:\n1 git submodule update --init 由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下\n1 git checkout v1.0 2. Matter依赖项安装 Matter 构建依赖于以下软件包及环境库:\n1 2 3 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \\ libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \\ python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev 如果通过 build_examples.py 和 -with-ui 变体进行构建,也要安装 SDL2:\n1 sudo apt-get install libsdl2-dev 3. Matter环境构建 执行scripts/activate.sh脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。\n1 source scripts/activate.sh 如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):\n1 source scripts/bootstrap.sh 4. 安装zap 注意:zap 包目前不可用arm64(比如在 Raspberry PI 上编译时)。\n**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令: 1 node -v 如果安装的话不出意外会出现版本号。\nStep2:zap安装 1 2 3 cd connectedhomeip/scripts/tools/zap python3 zap_download.py 下面是安装日志:\n1 2 3 4 5 6 root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py 2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly 2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip 2023-06-19 13:29:20 root INFO Data downloaded, extracting ... 2023-06-19 13:29:25 root INFO Done extracting. export ZAP_INSTALL_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly Step3:配置zap环境变量 我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly,在此目录下有个 zap 脚本,我们这个位置一定要记住!!\n设置ZAP_DEVELOPMENT_PATH环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)\n1 export ZAP_DEVELOPMENT_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly Step4:运行zap引导程序 执行如下代码:\n1 ./run_zaptool.sh 效果如下:\nStep4:为了方便我们后续使用zap,我们设置root终端下自启动: 1 2 3 sudo su vi ~/.bashrc 在.bashrc文件最末添加如下代码,也就是配置zap环境变量\n1 export ZAP_DEVELOPMENT_PATH=/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly 保存退出!\n应用程序构建 在官方文档中提供有两种构建方式:\n通过脚本构建 使用 Gn 和 Ninja 命令构建 1. 通过脚本构建 1 ./build_script.sh EXAMPLE_DIR OUTPUT_DIR [ARGUMENTS] build_script.sh 是脚本的文件名; EXAMPLE_DIR 是示例项目的目录路径; OUTPUT_DIR 是构建输出的目录路径; [ARGUMENTS] 是可选的其他参数,用于设置gn和ninja命令的选项。 1.1 构建示例 1 ./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ chip_tests_zap_config=\\\u0026#34;app1\\\u0026#34; 1.2 运行构建 1 ./out/simulated/chip-app1 2. 通过 gn 和 ninja 构建应用程序 2.1 构建示例 1 2 3 source scripts/activate.sh gn gen --check --root=examples/placeholder/linux out/simulated --args=\u0026#34;chip_tests_zap_config=\\\u0026#34;app1\\\u0026#34;\u0026#34; ninja -C out/simulated 2.2 运行构建 1 2 3 cd ./out/app1/chip-app1 测试应用程序 在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码\n我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:\n1 2 3 4 5 6 cd out/debug ./chip-tool onoff on 0x654321 1 ./chip-tool onoff off 0x654321 1 ./chip-tool onoff read accepted-command-list 0x654321 1 ./chip-tool onoff read on-time 0x654321 1 具体更多的使用命令可参考:Chip tool\n参考 simulated_device_linux zap ","date":"2023-06-19T00:00:00Z","image":"https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover_hu65dff124932dfb42ad926fa313c00f10_270892_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/","title":"【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)"},{"content":"Matter学习笔记1 在了解Matter之前,可以选择先了解以下前提知识:\nmatter网络基础之—Thread matter网络基础之—Wi-Fi 边界路由器,网关和Wi-Fi接入点 Thread地址(IPv6 and RLOC16) 以上资料来自CSDN博主:Eagle115\n前言 近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。\nMatter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准。\nMatter 作为一个应用级的协议,向下屏蔽了设备制造商的生态和系统,让各种智能家居设备之间能相互通信。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。\nMatter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:\n低功耗蓝牙技术:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。 二维码进行配置:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。 Wi-Fi 技术进行高速数据传输:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。 Thread 协议进行低速数据传输:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。 Matter协议架构 1.Matter Over IPV6 该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。\nIPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。\n下面是IPV4 和 IPV6 的一些区别:\n区别 IPV4 IPV6 地址长度 32 bits 128 bits 地址数量 约4x10^9 约3.4×10^38 地址类型 公网地址和私有地址 全局地址和本地地址 地址分配方式 静态地址和动态地址 通过 DHCPv6 动态分配 安全性 IPsec(Internet协议安全标准) 为可选项 IPsec 为默认选项 \u0026mdash; \u0026mdash; \u0026mdash; 2.Matter协议架构 Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。\n为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此天生具备IP连接能力,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;\nMatter 还支持桥接等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行Bridge;\n由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!\n3.Matter标准协议架构 Matter标准协议架构总体流程分析:\n首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议Message Reliability Protocol);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。\n后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!\nMatter网络拓扑结构 原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。\n在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。\nMatter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层。而 6LoWPAN协议 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。\n因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。\nMesh组网 在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。\n目前最流行的全屋WiFi方案主要有两种:Mesh路由器组网和AC+AP两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。\n无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,无线Mesh网络中的AP可以采用无线连接的方式进行互连,并且AP间可以建立多跳的无线链路。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。\n这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:\n1.单一网络拓扑 在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是Thread/802.15.4网络、Wi-Fi网络或以太网网络。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,前提是所有段都在链路层桥接。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。\n在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。\n在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为Fabric。\n注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。\n2.星形网络拓扑 AP(Access Point):WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。 STA(Station):STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。 BR(Border Router):指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。 ED(End device):指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。 R(Router):指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。 SED(Sleepy End Device):指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。 星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。\n在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。\n该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。\n注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。\n设备数据模型(Date Model) 在 Matter 中的设备具有明确定义的数据模型 (DM),这是对设备功能的分层建模。在此层次结构的顶层,有一个Device。\n1.设备和端点(Node、Endpoint) 所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。\n一组节点包含了多组Endpoint(端点)。而每个端点都封装了一个功能集。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。\n2.节点角色(Node roles) 在Matter 中,每一个物理设备都被称之为Node,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!\nNode roles是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:\nCommissioner :执行调试的节点 。 控制器:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如开/关灯开关)具有控制器角色。 Controlee : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如On/Off Light Switch。开/关灯开关只能是控制器。它不能是受控人。 OTA Provider : 可以提供 OTA 软件更新的节点。 OTA 请求者:可以请求 OTA 软件更新的节点。 3.集群(Cluster) 在一个Endpoint中,一个 Node 有一个或多个Clusters。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的开/关集群,或可调光端点上的电平控制集群。\n一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。\n3.1 属性(Attributes) 在最后一层,我们会找到Attributes,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。\n3.2 命令(Commands) 除了 Attributes 之外,Clusters 还有Commands,也就是触发 Cluster 进行某种行为的指令。它们等同于Matter远程过程调用的 DM。命令类似于动词,例如Door Lock集群上的 lock door。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。\n3.3 事件(Events) 最后,Clusters 也可能有Events,它可以被认为是过去状态转换的记录。虽然属性代表当前状态,但事件是过去的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。\nEndpoint 0作为Utility Clusters保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。\n4. Cluster分类 cluster可以定义为工具(Utility) Cluster或应用(Application) Cluster。\n4.1 工具(Utility) Cluster 工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。\n作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster 示例:基本信息、诊断等。\n4.2 应用(Application) Cluster 应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。\n应用cluster示例:\nOn/Off cluster —— client向server发送命令 Temperature Measurement cluster —— server向client报告数据 应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。\n示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 示例:commissioning cluster的范围是配网,而不是测温。\n5. Clients and Servers Clusters 可能是Client Cluster或Server Cluster。服务器是有状态的,保存属性、事件和命令;而客户端是 无状态的,其职责是启动与远程服务器集群的交互,从而执行:\n读取和写入其远程属性。 读取其远程事件。 调用其远程命令。 虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有controller/peripheral 或 leader/follower关系。相反,关系是水平的:任何 Cluster 都可以是Server或Client。因此,对于不同的集群和功能,节点可能既是服务器又是客户端。\n例如,我们可能有两个台灯:节点 A和节点 B。两个节点都实现了一个开/关灯设备类型。此设备类型包括控制其各自物理光输出的开/关服务器集群。\n但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现开/关客户端集群,以便它可以控制服务器集群。\n在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。\n在下一节中,我们将详细介绍客户端和服务器集群如何交互: Interaction Model(交互模型)。\n交互模型 1.概念 如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。交互模型(IM),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。\n节点通过以下方式相互交互:\n读取和订阅属性和事件 写入属性 调用命令 每当一个节点与另一个节点建立加密通信序列时,它们就构成了交互关系。Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成,可以理解为 Node 之间的 IM 级消息。\nMatter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。\n1.1 发起者(Initiators )和目标(Targets) 在Matter中,节点的发起目标被称为发起者(Initiators ),而响应的节点则作为目标(Target)。一般来说,发起者是客户端集群,而目标是客户端集群。\n1.2 组(Groups) 在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。\n为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。\n1.3 路径(Path) 当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。\n注:Path 也可以使用Groups或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。\nPath这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。\nMatter Path 使用规范:\n1 2 \u0026lt;path\u0026gt; = \u0026lt;node\u0026gt; \u0026lt;endpoint\u0026gt; \u0026lt;cluster\u0026gt; \u0026lt;attribute | event | command\u0026gt; \u0026lt;path\u0026gt; = \u0026lt;group ID\u0026gt; \u0026lt;cluster\u0026gt; \u0026lt;attribute | event | command\u0026gt; 在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。\n1.4 定时和非定时(Timed \u0026amp; Untimed) 有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。\n2. Read Transactions 与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。\n2.1 读取请求操作(Read Request Action) 发起者 -\u0026gt; 目标\n在此 Action 中,Initiator 会查询 Target 提供的以下请求:\n属性请求:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。 事件请求:目标请求事件的零个或多个路径列表。 目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:\n2.2 报告请求数据(Report Data Action) 目标 -\u0026gt; 发起者\n在此 Action 中,Target 响应:\n属性报告(Attribute Reports):读取操作请求中请求的零个或多个报告属性的列表。 事件报告(Event Reports):零个或多个报告事件的列表。 抑制响应(Suppress Response):一个标志,用于确定是否应抑制对此操作的状态响应。 订阅 ID(Subscription ID):如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。 2.3 状态响应动作(Status Response Action) 目标 -\u0026gt; 发起者 -\u0026gt; 目标\n一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。\n一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。\n状态响应操作仅包含一个状态字段,该字段将确认操作成功或显示失败代码。\n3. Subscription Transaction 3.1 订阅请求操作(Subscribe Request Action) 发起者 -\u0026gt; 目标\n除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。\n订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。\n订阅请求操作包含:\nMin Interval Floor(最小间隔层):报告之间的最小间隔。 Max Interval Ceiling(最大区间上限):报告之间的最大间隔。 Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。 Event Reports(事件报告):零个或多个报告事件的列表。 在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:Primed Published Data。\n然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。\n目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。\n3.2 订阅响应操作(Subscribe Response Action) 目标 -\u0026gt; 发起者\n这是订阅交易的最后一个操作,并结束了该过程。这包括:\nSubscription ID(订阅 ID):标识订阅的整数。 Min Interval(最小间隔):最终确定的报告之间的最小间隔。 Max Interval(最大间隔):最终确定的报告之间的最大间隔。 4. Write Transactions 4.1 不定时写入事务(Untimed Write Transaction) 4.1.1 写请求操作(Write Request Action) 发起者 -\u0026gt; 目标\n与读取请求操作类似,在此操作中,发起者为目标提供:\nWrite Requests(写入请求):包含路径和数据的一个或多个元组的列表。 Timed Request(定时请求):一个标志,指示此操作是否是定时写入事务的一部分。 Suppress Response(抑制响应):指示是否应抑制响应状态操作的标志。 4.1.2 写响应操作(Write Response Action) 目标 -\u0026gt; 发起者\n4.1.3 不定时写入限制(Untimed Write Restrictions) 写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。\n为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。\n4.2 定时写入事务(Timed Write Transaction) 在定时写入事务中比非定时写入事务多了几个步骤。\n4.2.1 定时请求操作(Timed request action) 发起者 -\u0026gt; 目标\nInitiator 启动事务发送此操作,其中包含:\nTimeout:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。 一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。\n4.2.2 写请求操作(Write Request Action) 与前面描述的 4.1.1 写请求操作 相同。\n4.2.3 写响应操作(Write Response Action) 与前面描述的 4.1.2 写响应操作 相同。\n4.2.4 定时写入限制(Timed Write Restrictions) 定时请求动作、写请求动作和写响应动作是单播的。\n5.调用事务 调用事务用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。\n与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 交互模型:1.4.定时和非定时\n5.1 不定时调用事务 5.1.1 调用请求操作(Invoke Request Action) 发起者 -\u0026gt; 目标\n类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:\nInvoke Requests(调用请求):集群命令的路径(PATH)列表 ,以及命令的可选参数,名为 Command Fields。 Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。 Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。 Interaction ID:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。 5.1.2 调用响应操作(Invoke Response Action) 目标 -\u0026gt; 发起者\n目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:\nInvoke Responses(调用响应):发送的每个调用请求的命令响应或状态列表。 Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。 5.1.3 不定时调用限制 Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。\n为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。\n5.2 定时调用事务 与定时写入事务类似,定时调用事务也从定时请求操作开始。\n5.2.1 定时请求操作 发起者 -\u0026gt; 目标\nInitiator 启动事务发送此操作,其中包含:\nTimeout:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。 一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。\n5.2.2 调用请求操作(Invoke Request Action) 与前面描述的 5.1.1 调用请求操作 相同。\n5.2.3 调用响应操作(Invoke Response Action) 与前面描述的 5.1.2 调用响应操作 相同。\n5.2.4 定时调用限制(Timed Invoke Restrictions) 所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。\nInvoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。\n参考资料 https://developers.home.google.com/matter/primer/device-data-model#parts_list Matter技术及关键特性介绍 ","date":"2023-06-14T00:00:00Z","image":"https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover_hu4db83519daded61789268b571d06530d_135204_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/","title":"【Matter】Matter学习笔记1"},{"content":"nRF Connect SDK 支持Mattter Nordic提供的Matter用户指南 子页面:\nMatter概况 开始使用Matter 如何创建 Matter 最终产品 Matter网络拓扑结构 Thread:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。 WI-FI:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。 Ethernet(以太网):Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。 Matter binding(Matter协议):Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。 硬件平台 运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。\n硬件参考\nNodic nRF52840 PC: Ubuntu(20.04 或更新版本) Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡) 支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护) RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备 兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个Matter 样本兼容并编程) 软件平台 Linux PC withsoftware installed:\nnRFConnectSDK v2.1.1\nnRFCommand-line tools\nVisual Studio Code withnRFConnect ExtensionPack for VS Code RaspberryPi 4 runningOpenThreadBorder Router\n商业Matter生态系统测试方式 对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:\nMatter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器 Matter over Thread:在一台设备上配置边界路由器和控制器 Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具 注意:这里我们基于Matter over Thread:在一台设备上配置边界路由器和控制器进行过程演示。\nMatter over Thread::在一台设备上配置边界路由器和控制器 如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。\n在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。\n下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发\n1.要求 若要使用此设置,需要以下硬件:\n以下任意之一: 1 台装有 Ubuntu 的电脑(20.04 或更高版本) 1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS 1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样) 1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备 1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用物质样品之一进行编程)) 2.配置环境 要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。\nStep1.对样品编程 使用可用的 Matter 样本之一对 Matter 附件设备的开发套件进行编程。 我们建议使用Matter light bulb。\nStep2.Thread Border Router配置 在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 Thread Border Router页面上的使用 Docker 运行 OTBR 部分。\nStep3.Chip Tool配置 适用于 Linux 或 macOS 的 CHIP Tool 是 Matter controller 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。\n完成以下步骤:\na. 选择以下选项之一:\n仅适用于 Linux - 使用 Matter nRF Connect 发布 GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。 对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 CHIP TOOL页面中的构建说明。modules/lib/matter/examples/chip-tool b. 配置芯片工具控制器。 按照 Matter 文档中的使用 CHIP TOOL用户指南中的步骤完成以下操作:\n通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。 通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。 Step4.例程测试 根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。\n结语 这部分仅作为开发大纲,后面会出一系列系统教程,以Matter over Thread::在一台设备上配置边界路由器和控制器为例。\nNordic-Matter 演示教学\nMatter over Thread: Configuring Border Router and controller on one device\n","date":"2023-06-07T00:00:00Z","image":"https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover_huc64212d66a303c0299db7891fa23c614_59145_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/","title":"【Matter】Nordic-Mattter开发大纲"},{"content":"前言 最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是Github + Typora的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.\n所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。\n具体流程 当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。\n1. 创建GitHub工作流文件 在GitHub仓库中,转到.github/workflows目录并创建一个新文件,比如file_count.yml。该文件将定义运行自动化操作的工作流。\n2. 定义工作流 在file_count.yml文件中,添加以下代码:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 name: File Count Reminder on: schedule: - cron: \u0026#34;0 0 * * *\u0026#34; # Runs every day at midnight UTC jobs: count-files: runs-on: ubuntu-latest steps: - name: Check out code uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: \u0026#39;3.10\u0026#39; # Replace with the desired Python version - name: Count files and send email run: | pip install -r requirements.txt python send_email.py ${{ secrets.GITHUB_TOKEN }} 3. 创建requirements.txt文件 在GitHub仓库中创建一个名为requirements.txt的文件,并将以下内容添加到文件中:\n1 smtplib 4. 创建send_email.py文件 在GitHub仓库中创建一个名为send_email.py的文件,并将以下代码添加到文件中:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import os import smtplib from email.mime.text import MIMEText from email.header import Header def count_files(directory): file_count = 0 for root, dirs, files in os.walk(directory): file_count += len(files) return file_count def send_email(github_token, recipient, file_count): smtp_server = \u0026#39;smtp.gmail.com\u0026#39; smtp_port = 587 subject = \u0026#39;File Count Reminder\u0026#39; content = f\u0026#39;The repository has {file_count} files.\u0026#39; message = MIMEText(content, \u0026#39;plain\u0026#39;, \u0026#39;utf-8\u0026#39;) message[\u0026#39;From\u0026#39;] = Header(\u0026#39;GitHub Action\u0026#39;) message[\u0026#39;To\u0026#39;] = Header(recipient) message[\u0026#39;Subject\u0026#39;] = Header(subject) try: server = smtplib.SMTP(smtp_server, smtp_port) server.starttls() server.login(\u0026#39;githubaction@gmail.com\u0026#39;, github_token) server.sendmail(\u0026#39;githubaction@gmail.com\u0026#39;, recipient, message.as_string()) server.quit() print(\u0026#34;Email reminder sent to\u0026#34;, recipient) except Exception as e: print(\u0026#34;Failed to send email:\u0026#34;, str(e)) repository_path = \u0026#39;.\u0026#39; # Replace with the path to your repository if needed file_limit = 999 file_count = count_files(repository_path) if file_count \u0026gt; file_limit: github_token = os.environ.get(\u0026#39;INPUT_GITHUB_TOKEN\u0026#39;) default_email = os.environ.get(\u0026#39;GITHUB_ACTOR\u0026#39;) + \u0026#39;@users.noreply.github.com\u0026#39; send_email(github_token, default_email, file_count) else: print(\u0026#34;The repository has\u0026#34;, file_count, \u0026#34;files. No reminder needed.\u0026#34;) 使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。\n","date":"2023-05-31T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover_hucbce8390de2ea0a35e5136165fc15f47_34419_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/","title":"【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数"},{"content":"使用chip tool在ESP32-C3上进行matter开发 前提准备 请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)\nubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境\nPC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款蓝牙适配器\n编译 chip-tool 1.激活esp-matter环境 1 2 cd esp-idf . ./export.sh 1 2 cd esp-matter . ./export.sh 2.编译matter所需环境 step1:首先安装编译所需的依赖包: 1 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过) 1 2 3 # 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新 source scripts/bootstrap.sh 对于 MacOS,gdbguipython 包不会使用bootstrap.sh 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为gevent(依赖于gdbgui)构建轮子失败。\n对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。\n如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件\n1 2 python3 -m pip install -c scripts/setup/constraints.txt --no-cache --prefer-binary gdbgui==0.13.2.0 deactivate step3:激活编译matter环境 1 source scripts/activate.sh step4:启用 Ccache 以加快 IDF 构建速度 1 $ export IDF_CCACHE_ENABLE=1 3.构建CHIP TOOL 在 ~/esp/esp-matter/connectedhomeip/connectedhomeip目录下,执行命令\n1 ./gn_build.sh 执行完之后,会在根目录下生成 out/debug/standalone/chip-tool一个二进制文件。\n如果上述命令:./gn_build.sh执行失败,也可以执行如下命令:\n1 scripts/examples/gn_build_example.sh examples/chip-tool SOME-PATH/ 执行完毕后,在以下路径 connetedhomeip/connectedhomeip/SOME-PATH也可以发现生成了 chip-tool 工具\nchip-tool client 调试设备说明 为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前一次只支持调试和记忆一个设备。配置状态存储在/tmp/chip_tool_config.ini中;\n另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 获取受支持集群的列表 Usage: ./chip-tool cluster_name command_name [param1 param2 ...] +-------------------------------------------------------------------------------------+ | Clusters: | +-------------------------------------------------------------------------------------+ | * barriercontrol | | * basic | | * colorcontrol | | * doorlock | | * groups | | * iaszone | | * identify | | * levelcontrol | | * onoff | | * pairing | | * payload | | * scenes | | * temperaturemeasurement | +-------------------------------------------------------------------------------------+ 有关具体其他命令和使用方法详见 : https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool 要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:\n1.基于 BLE 调试 运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:\n1 chip-tool pairing ble-wifi ${NODE_ID_TO_ASSIGN} ${SSID} ${PASSWORD} 20202021 3840 ${NODE_ID_TO_ASSIGN}(必须是十进制数或0x- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。 ${SSID} 是 Wi-Fi SSID 可以是字符串,也可以是hex:XXXXXXXX SSID 的字节被编码为两位十六进制数字的形式。 ${PASSWORD} 是 Wi-Fi 密码,同样是字符串或十六进制数据 1 2 # 例如 chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq 202021 3840 2.通过IP与设备配对 下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。\n1 chip-tool pairing onnetwork ${NODE_ID_TO_ASSIGN} 20202021 下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。\n1 chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。\n1 chip-tool pairing code ${NODE_ID_TO_ASSIGN} MT:####### 在所有这些情况下,将为设备分配节点 ID ${NODE_ID_TO_ASSIGN} (必须是十进制数或以 0x 为前缀的十六进制数)。\n3.Trust store Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 \u0026ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。\n下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。\n1 chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 --paa-trust-store-path path/to/PAAs 4.忘记当前委托的设备 1 chip-tool pairing unpair 使用chip-tool点灯 1.matter环境激活 由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:\nstep1:新建一个名为 matter.sh 的脚本文件 1 vi matter.sh step2:复制以下内容到 matter.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #/bin/bash # matter.sh EPS_MATTER_PATH=\u0026#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter\u0026#34; if [ $1 -eq 1 ]; then export IDF_PATH=\u0026#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf\u0026#34; source /home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf/export.sh source $EPS_MATTER_PATH/export.sh export IDF_CCACHE_ENABLE=1 echo \u0026#34;enter matter dir\u0026#34; cd $EPS_MATTER_PATH fi step3:执行脚本以激活 matter 环境 1 source matter.sh 1 2.固件烧录 打开一个新的终端1,进入示例目录设置并编译烧写到评估板运行 1 cd ./esp/esp-matter/examples/light 设置要构建的 Matter 目标 目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标 1 2 3 4 5 # 命令1,通用命令,ESP32H2请执行命令2 idf.py set-target (target chip) # 命令2,ESP32H2专用命令 idf.py --preview set-target esp32h2 这里我使用的是 ESP32C3,所以执行以下命令即可\n1 idf.py set-target esp32c3 配置选项(可遵循默认配置即可,非特定配置可跳过这一步) 要构建特定配置(示例m5stack):\n1 2 rm sdkconfig idf.py -D \u0026#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults\u0026#39; build 注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。\n要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:\n1 idf.py menuconfig 构建应用程序 1 idf.py build 擦除Flash 构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。\n请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在functional description diagram中有所提及。\n1 2 idf.py -p (PORT) erase_flash idf.py -p (PORT) flash monitor 请替换(PORT)为您系统的正确 USB 设备名称(如/dev/ttyUSB0在 Linux 或/dev/tty.usbserial-101Mac 上)。\n查看USB设备,esp32c3设备名为 ttyUSB0,因此执行以下命令 :\n1 2 idf.py -p /dev/ttyUSB0 erase_flash idf.py -p /dev/ttyUSB0 flash monitor 注意此时的设备串口终端1暂时先不关闭,后面可使用CTRL+]关闭设备串口调试 注意:某些用户可能必须在设备出现在 /dev/tty 之前安装VCP 驱动程序。\n提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。\n3.项目调试 以下四种方式可以用于调试在ESP32上运行应用程序:\nPython Based Device Controller Standalone chip-tool iOS chip-tool App Android chip-tool App 注:这里使用 Standalone chip-tool进行项目调试\n打开一个新的终端2,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:\n1 2 3 4 cd esp-matter/connectedhomeip/connectedhomeip # 激活matter环境 source scripts/activate.sh 调试WIFI设备(ESP32、ESP32C3、ESP32S3) 如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看此链接\n执行下面命令将 matter 设备接入现有现有IP网络,这里我们基于BLE调试\n需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个购买链接\n接下来请按照我的步骤一步步执行:\nstep1:安装 blueman 软件 1 2 sudo apt install blueman #安装blueman软件 sudo /etc/init.d/bluetooth restart # 重启blueman服务 step2:确保你的蓝牙状态处于激活状态 1 2 3 # 查看蓝牙状态 sudo systemctl status bluetooth 如果未运行,请执行:\n1 2 sudo systemctl enable bluetooth sudo systemctl start bluetooth step3:确认蓝牙适配器已经被识别并启用 1 hciconfig -a 根据提示信息我们可以得知我的蓝牙适配器名为\u0026quot;hci0\u0026quot;,并且状态为 \u0026ldquo;DOWN\u0026rdquo;,因此我们需要启用该蓝牙适配器。\nstep4:启用蓝牙适配器 1 sudo hciconfig hci0 up step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击Adapters...---\u0026gt;Visibility Setting---\u0026gt;Always visible,这一步很关键,每次基于 BLE 调试都需要检查这一步!! step6:BLE调试,回到终端2,执行如下命令 1 2 3 cd esp-matter/connectedhomeip/connectedhomeip out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq 20202021 3840 注意:本机ip和matter设备ip必须在同一局域网下\n0x7283(必须是十进制数或0x- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。 jetbot 是 Wi-Fi SSID 可以是字符串,也可以是hex:XXXXXXXX SSID 的字节被编码为两位十六进制数字的形式。 jetbotwyq 是 Wi-Fi 密码,同样是字符串或十六进制数据 在终端1我们可以看到相关的ip信息:\nstep7:利用 chip tool 控制LED开关 1 2 3 4 # open led out/debug/chip-tool onoff on 0x7896 0x1 # close led out/debug/chip-tool onoff off 0x7896 0x1 这里的节点ID:0x7896需要和前面保持一致\nCHIP TOOL基于BLE调试完整过程 Your browser doesn't support HTML5 video. Here is a link to the video instead. 参考 CHIP Reference Setup ESP-IDF and CHIP Environment building and commissioning ","date":"2023-05-30T00:00:00Z","image":"https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover_hu0ba98275d6445c79f820f07c37ff307c_166978_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/","title":"【Matter】使用chip-tool在ESP32-C3上进行matter开发"},{"content":"Matter 环境构建参考文档 Matter支持用GN配置构建,一个快速且可扩展的元构建系统,生成输入到ninja。\n经过测试的操作系统 该构建系统已经在以下操作系统上进行了测试:\nmacOS 10.15 Debian 11 (64 bit required) Ubuntu 22.04 LTS 构建系统的特点 Matter构建系统有以下特点:\n速度非常快,占用空间小 跨平台处理: Linux, Darwin, Embedded Arm, 等等 多种工具链和跨工具链的依赖性 集成了自动测试框架: ninja check 自省:\u0026ldquo;gn desc\u0026rdquo;。 自动格式化: gn格式。 检查Matter的代码 要检查Matter资源库,请运行以下命令:\n1 git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git 同步子模块 如果你已经签出了Matter的代码,运行下面的命令来同步子模块:\n1 git submodule update --init 先决条件 在构建之前,你必须安装一些操作系统的特定依赖。\n1.在Linux上安装先决条件 在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:\n1 2 3 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\\ libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev 用户界面的构建 如果通过build_examples.py和with-ui变体构建,也要安装SDL2:\n1 sudo apt-get install libsdl2-dev 2.在macOS上安装先决条件 在macOS上,从 Mac App Store上安装 Xcode 。\n用户界面的构建 如果构建-with-ui变体,也要安装 SDL2 :\n1 brew install sdl2 3.在Raspberry Pi 4上安装先决条件 完成以下步骤:\n使用:在 micro SD 卡上rpi-imager安装适用于 arm64 架构的 Ubuntu 22.04 64 位服务器操作系统。 启动SD卡。 用默认的用户账户 \u0026ldquo;ubuntu \u0026ldquo;和密码 \u0026ldquo;ubuntu \u0026ldquo;登录。 继续执行 在 Linux 上安装先决条件。 安装一些Raspberry Pi的特定依赖项: 1 sudo apt-get install pi-Bluetooth avahi-utils 安装完 \u0026ldquo;pi-bluetooth \u0026ldquo;后,重新启动你的Raspberry Pi。 配置wpa_supplicant以存储永久变化 默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:\n编辑 dbus-fi.w1.wpa_supplicant1.service 文件以使用配置文件来代替,运行以下命令: 1 sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service 运行以下命令,将wpa_supplicant的启动参数改为提供的值: 1 ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf 通过运行以下命令添加wpa-supplicant配置文件: 1 sudo nano /etc/wpa_supplicant/wpa_supplicant.conf 在wpa-supplicant文件中添加以下内容: 1 2 ctrl_interface=DIR=/run/wpa_supplicant update_config=1 重新启动你的Raspberry Pi。 安装ZAP工具 bootstrap.sh将下载一个兼容的ZAP工具版本并将其设置在$PATH。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的Release 页面下载。\n1.Linux ARM Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置$ZAP_DEVELOPMENT_PATH(见下面 使用哪种ZAP一节)。\n文件scripts/setup/zap.json包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本Release。要作为源代码签出代码,相应的标签应该存在于zap中repository tags 列表中。\n命令示例:\n1 2 3 4 5 6 7 8 RUN set -x \\ \u0026amp;\u0026amp; mkdir -p /opt/zap-${ZAP_VERSION} \\ \u0026amp;\u0026amp; git clone https://github.com/project-chip/zap.git /opt/zap-${ZAP_VERSION} \\ \u0026amp;\u0026amp; cd /opt/zap-${ZAP_VERSION} \\ \u0026amp;\u0026amp; git checkout ${ZAP_VERSION} \\ \u0026amp;\u0026amp; npm config set user 0 \\ \u0026amp;\u0026amp; npm ci ENV ZAP_DEVELOPMENT_PATH=/opt/zap-${ZAP_VERSION} 2.使用哪种ZAP ZAP工具脚本使用以下检测,按重要性排序:\n$ZAP_DEVELOPMENT_PATH指向一个ZAP检出。\n如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。\n$ZAP_INSTALL_PATH指向zap-linux.zip或`zap-m\n为构建做准备 在运行任何其他构建命令之前,scripts/activate.sh的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。\n运行以下命令:\n1 source scripts/activate.sh 1.更新环境 如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:\n1 source scripts/bootstrap.sh 脚本 scripts/bootstrap.sh从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。\n为主机操作系统(Linux或macOS)进行构建 运行以下命令,为主机平台构建所有的源代码、库和测试:\n1 2 3 4 5 source scripts/activate.sh gn gen out/host ninja -C out/host 这些命令生成了一个适合调试的配置。要配置一个构建,请指定is_debug=false:\n1 2 3 gn gen out/host --args=\u0026#39;is_debug=false\u0026#39; 。 ninja -C out/host **注意:**目录名称 \u0026ldquo;out/host \u0026ldquo;可以是任何目录,通常是在out目录下构建。这个例子使用 host 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过gn args重新配置。\n要运行所有测试,请运行以下命令:\n1 ninja -C out/host check 要想只运行src/inet/tests中的测试,可以运行以下命令:\n1 ninja -C out/host src/inet/tests:test_run **注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:\n1 ninja: no work to do 这意味着测试在之前的构建中通过了。\n使用build_examples.py 该脚本./scripts/build/build_examples.py提供了一个统一的编译构建接口,可以使用gn、cmake、ninja和其他必要的工具来编译各种平台。\n使用 ./scripts/build/build_examples.py targets 来查看支持的目标。\n构建命令的例子:\n1 2 3 4 5 6 7 8 9 10 11 # 编译并在主机上运行所有测试: ./scripts/build/build_examples.py --target linux-x64-test build # 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang) ./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build # 编译一个esp32的例子 ./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build # 编译一个 nrf 示例 ./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build 1.libfuzzer单元测试 libfuzzer单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如asan应该被使用。\n可执行以下命令:\n1 ./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build 之后,测试应该被定位在out/linux-x64-tests-lang-asan-libfuzzer/tests/。\nossfuzz的配置 ossfuzz配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如$CFLAGS、$CXXFLAGS和$lib_fuzzing_engine。\n你可能需要libfuzzer+asan的构建来代替本地测试。\n构建自定义配置 构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:\n将--args选项传递给gn gen。 在输出目录上运行gn args。 编辑输出目录下的args.gn。 要配置一个新的构建或编辑现有构建的参数,请运行以下命令:\n1 2 3 4 5 source scripts/activate.sh gn args out/custom ninja -C out/custom 两个关键的内置构建参数是 target_os 和 target_cpu,它们分别控制构建的操作系统和CPU。\n要查看所有可用的构建参数的帮助,请运行以下命令:\n1 2 gn gen out/custom gn args --list out/custom 构建实例 你可以通过两种方式构建例子。\n1.将例子作为独立的项目来构建 要把例子作为单独的项目来构建,在Matter的third_party directory,运行下面的命令,输入正确的路径到例子的正确路径(这里是 \u0026ldquo;chip-shell\u0026rdquo;):\n1 2 3 cd examples/shell gn gen out/debug ninja -C out/debug 2.在顶层建立实例 你可以在Matter项目的顶层构建例子。请看下面的统一构建一节了解详情。\n统一构建 要构建一个近似于连续构建集的统一配置,请运行以下命令:\n1 2 3 4 5 source scripts/activate.sh gn gen out/unified --args=\u0026#39;is_debug=true target_os=\u0026#34;all\u0026#34;\u0026#39; ninja -C out/unified all 你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。\n这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:\n1 2 ninja -C out/unified host_gcc ninja -C out/unified check_host_gcc 用配置的名称替换host_gcc,它可以在根目录下的 \u0026ldquo;BUILD.gn \u0026ldquo;中找到。\n你也可以用参数对生成的配置进行微调。比如说\n1 gn gen out/unified --args=\u0026#39;is_debug=true target_os=\u0026#34;all\u0026#34; enable_host_clang_build=false\u0026#39; 完整的列表请参见根目录BUILD.gn。\n在统一的构建中,目标有多个实例,需要通过添加通过添加(toolchain)后缀来区分。使用gn ls out/debug来列出所有的目标实例。例如:\n1 gn desc out/unified \u0026#39;//src/controller(//build/toolchain/host:linux_x64_clang)\u0026#39; **注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 必须作为构建参数提供。例如,要添加 Simplelink cc13x2_26x2 例子到统一构建中,安装SysConfig 并添加以下构建:\n1 gn gen out/unified --args=\u0026#34;target_os=\\\u0026#34;all\\\u0026#34; enable_ti_simplelink_builds=true \u0026gt; ti_sysconfig_root=\\\u0026#34;/path/to/sysconfig\\\u0026#34;\u0026#34; 获得帮助 GN集成了帮助,你可以通过gn help命令访问。\n请确保查看以下推荐的主题:\n1 2 3 gn帮助执行 gn help 语法 gn help toolchain 也可参见 快速入门指南。\n自省 GN有各种自省工具来帮助你检查构建配置。下面的例子以out/host输出目录为例:\n显示一个输出目录中的所有目标:\n1 gn ls out/host 显示所有将被构建的文件:\n1 gn output out/host \u0026#39;*\u0026#39; 显示配置的目标的GN表示:\n1 gn desc out/host //src/inet --all 将整个构建的GN表示转为JSON格式:\n1 gn desc out/host/ \u0026#39;*\u0026#39; --all --format=json 显示依赖关系树:\n1 gn desc out/host //:all deps --tree --all 查找依赖性路径:\n1 gn path out/host //src/transport/tests:test //src/system 列出与`libCHIP\u0026rsquo;连接的有用信息:\n1 2 3 4 5 6 gn desc out/host //src/lib include_dirs gn desc out/host //src/lib defines gn desc out/host //src/lib outputs # 一切都是JSON格式 gn desc out/host //src/lib --format=json 覆盖范围 代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。\n运行以下命令来启动该脚本:\n1 ./scripts/build_coverage.sh 默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:\n1 2 3 4 5 6 7 8 -c, --code 指定收集覆盖数据的范围。 core\u0026#34;:从Matter SDK的核心堆栈中收集覆盖数据。--default clusters\u0026#34;:从Matter SDK中的cluster实现中收集覆盖数据。 \u0026#39;all\u0026#39;:收集Matter SDK的覆盖数据。 -t, --tests 指定哪些工具来运行覆盖率检查。 \u0026#39;unit\u0026#39;: 运行单元测试来驱动覆盖率检查。--default \u0026#39;yaml\u0026#39;: 运行yaml测试来驱动覆盖率检查。 \u0026#39;all\u0026#39;: 运行单元和yaml测试来驱动覆盖率检查。 此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): matter coverage。\n维护事项 如果你对GN构建系统做了任何改变,下一次构建会自动重新生成ninja文件。不需要做任何事情。\n","date":"2023-05-24T00:00:00Z","image":"https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/cover_hu3d03a01dcc18bc5be0e67db3d8d209a6_235714_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/","title":"【Matter】Matter环境构建参考文档"},{"content":"esp-matter环境下的应用实践 前提准备 请确保你本地已经配置好 esp-idf 及esp-matter环境,可参考此博客【Matter】esp-matter开发环境搭建\n设置环境变量 1.ESP-IDF 根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:\n1 sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。\n1 2 cd ./esp/esp-idf source export.sh 2.ESP-Matter Linux macOS 由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见此处\n在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:\n1 2 3 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \\ libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \\ python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev 准备编译matter所需环境。注:如切换了其他分支需要重新运行\n1 2 cd ./esp/esp-matter/connectedhomeip/connectedhomeip source scripts/bootstrap.sh 激活编译matter环境\n1 2 cd ./esp/esp-matter/connectedhomeip/connectedhomeip source scripts/activate.sh Matter Example编译下载 1.激活esp-matter环境 1 2 cd esp-idf . ./export.sh 1 2 cd esp-matter . ./export.sh 2.选择esp设备 1 2 3 cd esp-matter/examples/light idf.py set-target esp32c3 初次执行这个命令发生了如下报错:\n1 2 3 4 5 ... AttributeError: \u0026#39;HTTPResponse\u0026#39; object has no attribute \u0026#39;strict\u0026#39; ... 在GitHub上参考此issue,并执行以下命令:\n1 pip install -U \u0026#34;urllib3\u0026lt;2\u0026#34; 同时重新执行esp-matter安装脚本:\n由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此issue\n1 2 3 4 5 rm -rf esp-matter/connectedhomeip/connectedhomeip/.environment cd esp-matter ./install.sh 1 pip install -U \u0026#34;urllib3\u0026lt;2\u0026#34; 然后回到示例工程下继续执行esp设备选择\n1 2 3 cd esp-matter/examples/light idf.py set-target esp32c3 此时发生了新的错误:\n由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:\n1 2 sudo rm -r esp-matter/examples/light/build idf.py set-target esp32c3 最后成功解决问题:\n3.编译工程 1 idf.py build 4.SDK烧写 第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令\n1 idf.py erase_flash 烧录程序并打开串口监视\n1 idf.py flash monitor 可以看到烧录进度:\n包括串口监视器的提示信息,同时执行以下命令可退出串口监视:\n1 CTRL + ] 那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。\n参考链接:\nMatter Over Wifi 例程体验(CHIP Over Wifi)\nESP-Matter 环境测试\nmatter搭建环境\nhttps://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html\n","date":"2023-05-06T00:00:00Z","image":"https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover_hub61065a780e4610b8a863ce12cf0078a_240369_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/","title":"【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)"},{"content":"esp-matter开发环境搭建 前提准备 1.Ubuntu22.04(磁盘容量不小于80G) 2.科学上网环境 由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。\n参考链接:【经验分享】Linux 环境下v2ray的使用\nesp-idf 开发环境搭建 1.ESP-IDF 依赖环境安装 参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html\n1 sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:\nProblem1:执行 git submodule 速度慢 Problem2:执行install.sh 速度慢 所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。\n2.Problem1 solution 首先使用递归克隆命令克隆整个仓库到文件夹下\n1 2 3 4 5 mkdir /home/kurisaw/Desktop/esp git clone --recursive https://github.com/espressif/esp-idf.git git submodule update --init --recursive 由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:\njihu-mirror 使用(推荐) submodule-update 使用(不推荐) 2.1 jihu-mirror 使用(推荐) Step 1: 1 2 git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git cd esp-gitee-tools Step 2: 1 2 3 // 使用如下命令将仓库的 URL 进行替换: git config --global url.https://jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf 当我们使用命令 git clone https://github.com/espressif/esp-idf 时,默认的 URL https://github.com/espressif/esp-idf 将被自动替换成 https://jihulab.com/esp-mirror/espressif/esp-idf。\nStep 3: 1 2 3 // 启用镜像URL ./jihu-mirror.sh set 使用命令 ./jihu-mirror.sh unset 恢复,不使用镜像的 URL。\nStep 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库 1 git clone --recursive https://github.com/espressif/esp-idf.git 当然如果不想使用镜像的URL可以使用如下命令进行恢复:\n1 ./jihu-mirror.sh unset 2.2 submodule-update 使用(不推荐) Step 1:\n1 git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git Step 2:\n1 2 3 // 仅克隆 esp-idf,不包含子模块 git clone https://gitee.com/EspressifSystems/esp-idf.git Step 3: 可以有两种方式来更新 submodules。\n方式一\n进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:\n1 2 cd esp-gitee-tools export EGT_PATH=$(pwd) 进入 esp-idf 目录执行 submodule-update.sh 脚本:\n1 2 cd esp-idf $EGT_PATH/submodule-update.sh 方式二\nsubmodule-update.sh 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:submodule-update.sh PATH_OF_PROJ。\n假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:\n1 2 cd esp-gitee-tools ./submodule-update.sh ~/git/esp32-sdk/esp-idf 如果要更新其他工程,可以同样方式。\n值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!\n3.Problem2 solution 下面说第二个问题:执行./install.sh速度慢的问题\n在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 IDF_GITHUB_ASSETS 的环境变量来指定这个地址。在设置了 IDF_GITHUB_ASSETS 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件\n1 export IDF_GITHUB_ASSETS=\u0026#34;dl.espressif.com/github_assets\u0026#34; 然后再执行安装命令\n1 ./install.sh 在这还报了一个错误\n我们根据提示安装python3.10-venv,并再次执行安装命令:\n1 2 3 apt install python3.10-venv ./install.sh 至此,esp-idf 的安装工具就告一段落了。\nesp-matter开发环境搭建 参考:【乐鑫 Matter SDK GitHub】\n**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:./jihu-mirror.sh unset取消esp镜像!! **\n1 git clone --recursive https://github.com/espressif/esp-matter.git 若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。\n1 git submodule update --init --recursive 执行安装命令:\n1 ./install.sh 本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错\u0026hellip;\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 Building wheel for pycryptodome (setup.py): started error: subprocess-exited-with-error × python setup.py bdist_wheel did not run successfully. │ exit code: 1 ╰─\u0026gt; See above for output. note: This error originates from a subprocess, and is likely not a problem with pip. Building wheel for pycryptodome (setup.py): finished with status \u0026#39;error\u0026#39; ERROR: Failed building wheel for pycryptodome Running setup.py clean for pycryptodome Building wheel for gevent (pyproject.toml): started ...... 我们查看install.sh文件\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #!/usr/bin/env bash set -e basedir=$(dirname \u0026#34;$0\u0026#34;) ESP_MATTER_PATH=$(cd \u0026#34;${basedir}\u0026#34;; pwd) MATTER_PATH=${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip export ESP_MATTER_PATH echo \u0026#34;\u0026#34; echo \u0026#34;Running Matter Setup\u0026#34; echo \u0026#34;\u0026#34; source ${MATTER_PATH}/scripts/bootstrap.sh echo \u0026#34;\u0026#34; echo \u0026#34;Installing zap-cli\u0026#34; echo \u0026#34;\u0026#34; # Run the zap_download.py and extract the path of installed binary # eg output before cut: \u0026#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly\u0026#34; # output after cut: zap/zap-v2023.03.06-nightly # TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged zap_path=`python3 ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py \\ --sdk-root ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly \\ --extract-root .zap 2\u0026gt;/dev/null | cut -d= -f2` # Check whether the download is successful. if [ -z $zap_path ]; then echo \u0026#34;Failed to install zap-cli\u0026#34; deactivate exit 1 fi # Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path if [ -d \u0026#34;${ESP_MATTER_PATH}/.zap\u0026#34; ]; then rm -r ${ESP_MATTER_PATH}/.zap fi mkdir ${ESP_MATTER_PATH}/.zap mv $zap_path/* ${ESP_MATTER_PATH}/.zap/ rm -r $zap_path chmod +x ${ESP_MATTER_PATH}/.zap/zap-cli echo \u0026#34;\u0026#34; echo \u0026#34;Building host tools\u0026#34; echo \u0026#34;\u0026#34; gn --root=\u0026#34;${MATTER_PATH}\u0026#34; gen ${MATTER_PATH}/out/host ninja -C ${MATTER_PATH}/out/host echo \u0026#34;\u0026#34; echo \u0026#34;Host tools built at: ${MATTER_PATH}/out/host\u0026#34; echo \u0026#34;\u0026#34; echo \u0026#34;\u0026#34; echo \u0026#34;Exit Matter environment\u0026#34; echo \u0026#34;\u0026#34; deactivate echo \u0026#34;\u0026#34; echo \u0026#34;Installing python dependencies for mfg_tool\u0026#34; echo \u0026#34;\u0026#34; python3 -m pip install -r ${ESP_MATTER_PATH}/tools/mfg_tool/requirements.txt echo \u0026#34;\u0026#34; echo \u0026#34;Installing python dependencies for Matter\u0026#34; echo \u0026#34;\u0026#34; python3 -m pip install -r ${ESP_MATTER_PATH}/requirements.txt echo \u0026#34;All done! You can now run:\u0026#34; echo \u0026#34;\u0026#34; echo \u0026#34; . ${basedir}/export.sh\u0026#34; echo \u0026#34;\u0026#34; 发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:\n1 2 3 4 5 sudo apt install build-essential python3-dev sudo apt-get install pkg-config sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev 接着在安装zap-cli的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译\n1 2 3 4 5 sudo apt-get install libssl-dev sudo apt-get install pip ./install.sh 最后看到All done!即代表环境安装成功!\n至此,esp-matter开发环境搭建成功!\n","date":"2023-05-04T00:00:00Z","image":"https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover_huabdcd8d32271ef5f0289704c9f451cf6_220565_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/","title":"【Matter】esp-matter开发环境搭建"},{"content":"Linux 环境下v2ray的使用 v2ray官方文档:https://v2raya.org/\ncurl安装 1 2 apt-get purge libcurl4 apt-get install curl v2ray镜像脚本安装 1 curl -Ls https://mirrors.v2raya.org/go.sh | sudo bash 出现该提示信息则表示安装成功:info: V2Ray v5.4.1 is installed.\n接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray\n1 sudo systemctl disable v2ray --now v2ray软件安装 仓库release地址:https://github.com/v2rayA/v2rayA/releases\n选择合适自己 Linux 内核架构,可以使用dpkg --print-architecture查看\n这里我选择``下载到 Linux 共享文件夹\n将共享文件夹下的installer_debian_amd64_2.0.5.deb文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装\n启动v2raya进程 1 sudo systemctl start v2raya.service 设置开机自启动 1 sudo systemctl enable v2raya.service v2ray使用 打开火狐浏览器,输入 http://localhost:2017/\n输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建\n导入我们的机场订阅地址\n选择想要使用的节点后,点击 Ready\nv2ray Settings 我们点击网页上右上角的Setting,进行如下修改\n测试 至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了\n","date":"2023-05-04T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/cover_huba1532e2363e5b99fb24669319d872ca_177311_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/","title":"【经验分享】Linux环境下v2ray的使用"},{"content":"1.FAL组件 1.1什么是FAL FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:\n支持静态可配置的分区表,并可关联多个 Flash 设备; 分区表支持 自动装载 。避免在多固件项目,分区表被多次定义的问题; 代码精简,对操作系统 无依赖 ,可运行于裸机平台,比如对资源有一定要求的 Bootloader; 统一的操作接口。保证了文件系统、OTA、NVM(例如:EasyFlash) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性; 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试; 通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。\n注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。\n关于存储,可以用一张图来解释:\n来源:ROM、RAM、FLASH、NVM……一文搞定\n1.2 使用ENV配置FAL 在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。\n我们下面正式讲解FAL组件的使用:\n首先打开ENV工具,根据以下路径打开FAL使能RT-Thread Components-\u0026gt;[*]FAL: flash abstraction layer,由于我们后面会用到SFUD,所以这里把FAL uses SFUD drivers一并使能,并修改FAL设备名称为W25Q128.\n完成上述操作后保存退出,并使用scons --target=mdk5重新生成MDK5文件并打开\n1.3 FAL SFUD 移植 为了提供示例,我们选用W25Q128 spi flash作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。\n由于目前RT-Thread的SFUD已经对W25Q128 完成支持,根据官方的使用手册,我们仅需编写fal_cfg.h文件完成对FAL_FLASH_DEV_TABLE及FAL_PART_TABLE的定义即可。文件存放路径:.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\board\\ports\\fal_cfg.h\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // fal.cfg.h /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-21 Wangyuqiang the first version */ #ifndef _FAL_CFG_H_ #define _FAL_CFG_H_ #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;board.h\u0026gt; #ifndef FAL_USING_NOR_FLASH_DEV_NAME #define NOR_FLASH_DEV_NAME \u0026#34;norflash0\u0026#34; #else #define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME #endif /* Flash device Configuration */ extern struct fal_flash_dev nor_flash0; /* flash device table */ #define FAL_FLASH_DEV_TABLE \\ { \\ \u0026amp;nor_flash0, \\ } /* Partition Configuration */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \\ { \\ {FAL_PART_MAGIC_WROD, \u0026#34;easyflash\u0026#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \\ {FAL_PART_MAGIC_WROD, \u0026#34;download\u0026#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \\ {FAL_PART_MAGIC_WROD, \u0026#34;wifi_image\u0026#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \\ {FAL_PART_MAGIC_WROD, \u0026#34;font\u0026#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \\ {FAL_PART_MAGIC_WROD, \u0026#34;filesystem\u0026#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \\ } #endif /* FAL_PART_HAS_TABLE_CFG */ #endif /* _FAL_CFG_H_ */ 此时编译的话是找不到该头文件的,需要我们在Keil中设置:\n在RTT FAL组件中的SFUD提供的fal_flash_dev对象默认的nor_flash0参数中,flash大小默认为8M,而W25Q128最大最16M,我们可以选择在.\\rt-thread\\components\\fal\\samples\\porting\\fal_flash_sfud_port.c文件中对struct fal_flash_dev nor_flash0进行修改:\n1 2 3 4 5 6 7 8 9 struct fal_flash_dev nor_flash0 = { .name = FAL_USING_NOR_FLASH_DEV_NAME, .addr = 0, .len = 16 * 1024 * 1024, .blk_size = 4096, .ops = {init, read, write, erase}, .write_gran = 1 }; 当然也可以选择不进行修改,根据大佬的原话就是因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-\u0026gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。\n同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径Hardware Drivers Config-\u0026gt;On-chip Peripheral Drivers-\u0026gt;[*] Enable soft SPI BUS-\u0026gt; [*] Enable soft SPI1 BUS (software simulation),这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。\n此时我们回到ENV主界面,进入RT-Thread Components-\u0026gt;Device Drivers-\u0026gt;Using Serial Flash Universal Driver,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可\n到这里,ENV的配置暂时告一段落!\n1.4 FAL SFUD 测试用例 为了验证W25Q128及软件模拟spi在SFUD框架上是否能够成功运行,我们在.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\board\\ports\\下新建一个soft_spi_flash_init.c文件,代码如下\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-21 Wangyuqiang the first version */ #include \u0026lt;rtthread.h\u0026gt; #include \u0026#34;spi_flash.h\u0026#34; #include \u0026#34;spi_flash_sfud.h\u0026#34; #include \u0026#34;drv_soft_spi.h\u0026#34; #include \u0026#34;drv_pin.h\u0026#34; #include \u0026#34;rtconfig.h\u0026#34; #define cs_pin\tGET_PINS(1,9) static int rt_soft_spi_flash_init(void) { int result = -1; result = rt_hw_softspi_device_attach(\u0026#34;sspi1\u0026#34;, \u0026#34;sspi10\u0026#34;, cs_pin); rt_kprintf(\u0026#34;value is %d\\n\u0026#34;,result); if(result == RT_EOK) { rt_kprintf(\u0026#34;rt_hw_softspi_device_attach successful!\\n\u0026#34;); } if (RT_NULL == rt_sfud_flash_probe(\u0026#34;W25Q128\u0026#34;, \u0026#34;sspi10\u0026#34;)) { return -RT_ERROR; } return RT_EOK; } INIT_COMPONENT_EXPORT(rt_soft_spi_flash_init); 这里我们需要指定一个片选引脚,我暂时使用了sspi2的SCK引脚作为片选,这里注意不要同时打开sspi1和sspi2,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是sspi1 bus及sspi10 device,并且挂载flash设备到sspi10。\n另外我们在.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\board\\ports\\下新建fal_sample.c文件,并编写测试代码:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 //fal_sample.c /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-21 Wangyuqiang the first version */ #include \u0026#34;rtthread.h\u0026#34; #include \u0026#34;rtdevice.h\u0026#34; #include \u0026#34;board.h\u0026#34; #include \u0026#34;fal.h\u0026#34; #define BUF_SIZE 1024 static int fal_test(const char *partiton_name) { int ret; int i, j, len; uint8_t buf[BUF_SIZE]; const struct fal_flash_dev *flash_dev = RT_NULL; const struct fal_partition *partition = RT_NULL; if (!partiton_name) { rt_kprintf(\u0026#34;Input param partition name is null!\\n\u0026#34;); return -1; } partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf(\u0026#34;Find partition (%s) failed!\\n\u0026#34;, partiton_name); ret = -1; return ret; } flash_dev = fal_flash_device_find(partition-\u0026gt;flash_name); if (flash_dev == RT_NULL) { rt_kprintf(\u0026#34;Find flash device (%s) failed!\\n\u0026#34;, partition-\u0026gt;flash_name); ret = -1; return ret; } rt_kprintf(\u0026#34;Flash device : %s \u0026#34; \u0026#34;Flash size : %dK \\n\u0026#34; \u0026#34;Partition : %s \u0026#34; \u0026#34;Partition size: %dK\\n\u0026#34;, partition-\u0026gt;flash_name, flash_dev-\u0026gt;len/1024, partition-\u0026gt;name, partition-\u0026gt;len/1024); /* erase all partition */ ret = fal_partition_erase_all(partition); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) erase failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } rt_kprintf(\u0026#34;Erase (%s) partition finish!\\n\u0026#34;, partiton_name); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0xFF) { rt_kprintf(\u0026#34;The erase operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } /* write 0x00 to the specified partition */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_write(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) write failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } i += len; } rt_kprintf(\u0026#34;Write (%s) partition finish! Write size %d(%dK).\\n\u0026#34;, partiton_name, i, i/1024); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0xFF, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0x00) { rt_kprintf(\u0026#34;The write operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } ret = 0; return ret; } static void fal_sample(void) { /* 1- init */ fal_init(); if (fal_test(\u0026#34;font\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;font\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;font\u0026#34;); } if (fal_test(\u0026#34;download\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;download\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;download\u0026#34;); } } MSH_CMD_EXPORT(fal_sample, fal sample); 1.5 测试结果 到这里就可以进行编译下载了,成功后的截图如下:\n2.DFS文件系统 2.1 什么是DFS DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:\n在 RT-Thread DFS 中,文件系统有统一的根目录,使用 / 来表示。而在根目录下的 f1.bin 文件则使用 /f1.bin 来表示,2018 目录下的 f1.bin 目录则使用 /data/2018/f1.bin 来表示。即目录的分割符号是 /,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 \\ 来作为目录的分割符)。\n2.2 DFS架构 RT-Thread DFS 组件的主要功能特点有:\n为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。 支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。 支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。 DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。\n2.3 使用ENV配置DFS 打开ENV,进入路径RT-Thread Components → DFS: device virtual file system,使能[*] DFS: device virtual file system\n由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能RT-Thread Components-\u0026gt;[*] Support legacy version for compatibility\n由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块W25Q128的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的Maximum sector size需要和W25Q128扇区大小保持一致,修改为4096,路径:RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module\n保存退出后使用scons --target=mdk5生成MDK5工程。\n2.4 DFS挂载到FAL分区测试 这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。\n我们接着修改fal_sample.c文件,修改后代码:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-21 Wangyuqiang the first version */ #include \u0026#34;rtthread.h\u0026#34; #include \u0026#34;rtdevice.h\u0026#34; #include \u0026#34;board.h\u0026#34; #include \u0026#34;fal.h\u0026#34; #include \u0026lt;dfs_posix.h\u0026gt; #define FS_PARTITION_NAME \u0026#34;filesystem\u0026#34; #define BUF_SIZE 1024 static int fal_test(const char *partiton_name) { int ret; int i, j, len; uint8_t buf[BUF_SIZE]; const struct fal_flash_dev *flash_dev = RT_NULL; const struct fal_partition *partition = RT_NULL; if (!partiton_name) { rt_kprintf(\u0026#34;Input param partition name is null!\\n\u0026#34;); return -1; } partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf(\u0026#34;Find partition (%s) failed!\\n\u0026#34;, partiton_name); ret = -1; return ret; } flash_dev = fal_flash_device_find(partition-\u0026gt;flash_name); if (flash_dev == RT_NULL) { rt_kprintf(\u0026#34;Find flash device (%s) failed!\\n\u0026#34;, partition-\u0026gt;flash_name); ret = -1; return ret; } rt_kprintf(\u0026#34;Flash device : %s \u0026#34; \u0026#34;Flash size : %dK \\n\u0026#34; \u0026#34;Partition : %s \u0026#34; \u0026#34;Partition size: %dK\\n\u0026#34;, partition-\u0026gt;flash_name, flash_dev-\u0026gt;len/1024, partition-\u0026gt;name, partition-\u0026gt;len/1024); /* erase all partition */ ret = fal_partition_erase_all(partition); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) erase failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } rt_kprintf(\u0026#34;Erase (%s) partition finish!\\n\u0026#34;, partiton_name); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0xFF) { rt_kprintf(\u0026#34;The erase operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } /* write 0x00 to the specified partition */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_write(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) write failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } i += len; } rt_kprintf(\u0026#34;Write (%s) partition finish! Write size %d(%dK).\\n\u0026#34;, partiton_name, i, i/1024); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0xFF, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0x00) { rt_kprintf(\u0026#34;The write operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } ret = 0; return ret; } static void fal_sample(void) { /* 1- init */ fal_init(); if (fal_test(\u0026#34;font\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;font\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;font\u0026#34;); } if (fal_test(\u0026#34;download\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;download\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;download\u0026#34;); } } MSH_CMD_EXPORT(fal_sample, fal sample); static void fal_elmfat_sample(void) { int fd, size; struct statfs elm_stat; struct fal_blk_device *blk_dev; char str[] = \u0026#34;elmfat mount to W25Q flash.\u0026#34;, buf[80]; /* fal init */ fal_init(); /* create block device */ blk_dev = (struct fal_blk_device *)fal_blk_device_create(FS_PARTITION_NAME); if(blk_dev == RT_NULL) rt_kprintf(\u0026#34;Can\u0026#39;t create a block device on \u0026#39;%s\u0026#39; partition.\\n\u0026#34;, FS_PARTITION_NAME); else rt_kprintf(\u0026#34;Create a block device on the %s partition of flash successful.\\n\u0026#34;, FS_PARTITION_NAME); /* make a elmfat format filesystem */ if(dfs_mkfs(\u0026#34;elm\u0026#34;, FS_PARTITION_NAME) == 0) rt_kprintf(\u0026#34;make elmfat filesystem success.\\n\u0026#34;); /* mount elmfat file system to FS_PARTITION_NAME */ if(dfs_mount(FS_PARTITION_NAME, \u0026#34;/\u0026#34;, \u0026#34;elm\u0026#34;, 0, 0) == 0) rt_kprintf(\u0026#34;elmfat filesystem mount success.\\n\u0026#34;); /* Get elmfat file system statistics */ if(statfs(\u0026#34;/\u0026#34;, \u0026amp;elm_stat) == 0) rt_kprintf(\u0026#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\\n\u0026#34;, elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree); if(mkdir(\u0026#34;/user\u0026#34;, 0x777) == 0) rt_kprintf(\u0026#34;make a directory: \u0026#39;/user\u0026#39;.\\n\u0026#34;); rt_kprintf(\u0026#34;Write string \u0026#39;%s\u0026#39; to /user/test.txt.\\n\u0026#34;, str); /* Open the file in create and read-write mode, create the file if it does not exist*/ fd = open(\u0026#34;/user/test.txt\u0026#34;, O_WRONLY | O_CREAT); if (fd \u0026gt;= 0) { if(write(fd, str, sizeof(str)) == sizeof(str)) rt_kprintf(\u0026#34;Write data done.\\n\u0026#34;); close(fd); } /* Open file in read-only mode */ fd = open(\u0026#34;/user/test.txt\u0026#34;, O_RDONLY); if (fd \u0026gt;= 0) { size = read(fd, buf, sizeof(buf)); close(fd); if(size == sizeof(str)) rt_kprintf(\u0026#34;Read data from file test.txt(size: %d): %s \\n\u0026#34;, size, buf); } } MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample); 2.5 测试结果 测试结果如下:\n3.Easyflash移植到FAL分区 3.1 简述EasyFlash 关于EasyFlash的来源我们已经讲过了,此处不再赘述。EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。\nEasyFlash不仅能够实现对产品的 设定参数 或 运行日志 等信息的掉电保存功能,还封装了简洁的 增加、删除、修改及查询 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。\n3.2EasyFlash软件包使用 打开ENV进入路径:RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.,选择软件包版本为最新版。\n配置后退出ENV,同时使用pkgs --update下载软件包,然后再使用scons --target=mdk5重新生成MDK5文件\n3.3 移植easyflash 下载完easyflash软件包后,我们复制.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\packages\\EasyFlash-latest\\ports\\ef_fal_port.c到目录.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\board\\ports\\easyflash\\ef_fal_port.c,双击打开该文件,完成以下修改:\n1 2 // 修改 FAL_EF_PART_NAME 为 easyflash #define FAL_EF_PART_NAME \u0026#34;easyflash\u0026#34; 1 2 3 4 // 修改环境变量内容为 {\u0026#34;boot_times\u0026#34;, \u0026#34;0\u0026#34;},这里我们先只设置一个开机次数 static const ef_env default_env_set[] = { {\u0026#34;boot_times\u0026#34;, \u0026#34;0\u0026#34;}, }; 3.4 编写Easyflash测试用例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-04-21 Wangyuqiang the first version */ #include \u0026#34;rtthread.h\u0026#34; #include \u0026#34;rtdevice.h\u0026#34; #include \u0026#34;board.h\u0026#34; #include \u0026#34;fal.h\u0026#34; #include \u0026lt;dfs_posix.h\u0026gt; #include \u0026#34;easyflash.h\u0026#34; #include \u0026lt;stdlib.h\u0026gt; #define FS_PARTITION_NAME \u0026#34;filesystem\u0026#34; #define BUF_SIZE 1024 static int fal_test(const char *partiton_name) { int ret; int i, j, len; uint8_t buf[BUF_SIZE]; const struct fal_flash_dev *flash_dev = RT_NULL; const struct fal_partition *partition = RT_NULL; if (!partiton_name) { rt_kprintf(\u0026#34;Input param partition name is null!\\n\u0026#34;); return -1; } partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf(\u0026#34;Find partition (%s) failed!\\n\u0026#34;, partiton_name); ret = -1; return ret; } flash_dev = fal_flash_device_find(partition-\u0026gt;flash_name); if (flash_dev == RT_NULL) { rt_kprintf(\u0026#34;Find flash device (%s) failed!\\n\u0026#34;, partition-\u0026gt;flash_name); ret = -1; return ret; } rt_kprintf(\u0026#34;Flash device : %s \u0026#34; \u0026#34;Flash size : %dK \\n\u0026#34; \u0026#34;Partition : %s \u0026#34; \u0026#34;Partition size: %dK\\n\u0026#34;, partition-\u0026gt;flash_name, flash_dev-\u0026gt;len/1024, partition-\u0026gt;name, partition-\u0026gt;len/1024); /* erase all partition */ ret = fal_partition_erase_all(partition); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) erase failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } rt_kprintf(\u0026#34;Erase (%s) partition finish!\\n\u0026#34;, partiton_name); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0xFF) { rt_kprintf(\u0026#34;The erase operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } /* write 0x00 to the specified partition */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0x00, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_write(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) write failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } i += len; } rt_kprintf(\u0026#34;Write (%s) partition finish! Write size %d(%dK).\\n\u0026#34;, partiton_name, i, i/1024); /* read the specified partition and check data */ for (i = 0; i \u0026lt; partition-\u0026gt;len;) { rt_memset(buf, 0xFF, BUF_SIZE); len = (partition-\u0026gt;len - i) \u0026gt; BUF_SIZE ? BUF_SIZE : (partition-\u0026gt;len - i); ret = fal_partition_read(partition, i, buf, len); if (ret \u0026lt; 0) { rt_kprintf(\u0026#34;Partition (%s) read failed!\\n\u0026#34;, partition-\u0026gt;name); ret = -1; return ret; } for(j = 0; j \u0026lt; len; j++) { if (buf[j] != 0x00) { rt_kprintf(\u0026#34;The write operation did not really succeed!\\n\u0026#34;); ret = -1; return ret; } } i += len; } ret = 0; return ret; } static void fal_sample(void) { /* 1- init */ fal_init(); if (fal_test(\u0026#34;font\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;font\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;font\u0026#34;); } if (fal_test(\u0026#34;download\u0026#34;) == 0) { rt_kprintf(\u0026#34;Fal partition (%s) test success!\\n\u0026#34;, \u0026#34;download\u0026#34;); } else { rt_kprintf(\u0026#34;Fal partition (%s) test failed!\\n\u0026#34;, \u0026#34;download\u0026#34;); } } MSH_CMD_EXPORT(fal_sample, fal sample); static void fal_elmfat_sample(void) { int fd, size; struct statfs elm_stat; struct fal_blk_device *blk_dev; char str[] = \u0026#34;elmfat mount to W25Q flash.\u0026#34;, buf[80]; /* fal init */ fal_init(); /* create block device */ blk_dev = (struct fal_blk_device *)fal_blk_device_create(FS_PARTITION_NAME); if(blk_dev == RT_NULL) rt_kprintf(\u0026#34;Can\u0026#39;t create a block device on \u0026#39;%s\u0026#39; partition.\\n\u0026#34;, FS_PARTITION_NAME); else rt_kprintf(\u0026#34;Create a block device on the %s partition of flash successful.\\n\u0026#34;, FS_PARTITION_NAME); /* make a elmfat format filesystem */ if(dfs_mkfs(\u0026#34;elm\u0026#34;, FS_PARTITION_NAME) == 0) rt_kprintf(\u0026#34;make elmfat filesystem success.\\n\u0026#34;); /* mount elmfat file system to FS_PARTITION_NAME */ if(dfs_mount(FS_PARTITION_NAME, \u0026#34;/\u0026#34;, \u0026#34;elm\u0026#34;, 0, 0) == 0) rt_kprintf(\u0026#34;elmfat filesystem mount success.\\n\u0026#34;); /* Get elmfat file system statistics */ if(statfs(\u0026#34;/\u0026#34;, \u0026amp;elm_stat) == 0) rt_kprintf(\u0026#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\\n\u0026#34;, elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree); if(mkdir(\u0026#34;/user\u0026#34;, 0x777) == 0) rt_kprintf(\u0026#34;make a directory: \u0026#39;/user\u0026#39;.\\n\u0026#34;); rt_kprintf(\u0026#34;Write string \u0026#39;%s\u0026#39; to /user/test.txt.\\n\u0026#34;, str); /* Open the file in create and read-write mode, create the file if it does not exist*/ fd = open(\u0026#34;/user/test.txt\u0026#34;, O_WRONLY | O_CREAT); if (fd \u0026gt;= 0) { if(write(fd, str, sizeof(str)) == sizeof(str)) rt_kprintf(\u0026#34;Write data done.\\n\u0026#34;); close(fd); } /* Open file in read-only mode */ fd = open(\u0026#34;/user/test.txt\u0026#34;, O_RDONLY); if (fd \u0026gt;= 0) { size = read(fd, buf, sizeof(buf)); close(fd); if(size == sizeof(str)) rt_kprintf(\u0026#34;Read data from file test.txt(size: %d): %s \\n\u0026#34;, size, buf); } } MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample); static void easyflash_sample(void) { /* fal init */ fal_init(); /* easyflash init */ if(easyflash_init() == EF_NO_ERR) { uint32_t i_boot_times = NULL; char *c_old_boot_times, c_new_boot_times[11] = {0}; /* get the boot count number from Env */ c_old_boot_times = ef_get_env(\u0026#34;boot_times\u0026#34;); /* get the boot count number failed */ if (c_old_boot_times == RT_NULL) c_old_boot_times[0] = \u0026#39;0\u0026#39;; i_boot_times = atol(c_old_boot_times); /* boot count +1 */ i_boot_times ++; rt_kprintf(\u0026#34;===============================================\\n\u0026#34;); rt_kprintf(\u0026#34;The system now boot %d times\\n\u0026#34;, i_boot_times); rt_kprintf(\u0026#34;===============================================\\n\u0026#34;); /* interger to string */ sprintf(c_new_boot_times, \u0026#34;%d\u0026#34;, i_boot_times); /* set and store the boot count number to Env */ ef_set_env(\u0026#34;boot_times\u0026#34;, c_new_boot_times); ef_save_env(); } } MSH_CMD_EXPORT(easyflash_sample, easyflash sample); 3.5 测试结果 打开串口助手,输入命令:\n1 msh /\u0026gt;easyflash_sample 第一次命令调用:\n第二次RESET开发板后调用:\n4.结语 至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!\n5.联系 Email :yifang.wangyq@foxmail.com Github Address :https://github.com/kurisaW My Website :https://kurisaw.github.io ","date":"2023-04-23T00:00:00Z","image":"https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover_hue90c124f4d3c5094341e1772579f0b35_161591_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/","title":"【NXP】LPC55S69_FAL分区管理与easyflash变量管理"},{"content":"RT-Thread网络框架:BSD网络接口\u0026amp;SAL套接字抽象层 基础知识 1.TCP与UDP的区别 TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。\nUDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。\nOSI七层模型和TCP/IP四层模型详解请看此处\n区别:\nTCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。 TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。 TCP面向字节流;UDP面向报文。 TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。 TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。 TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。 2.TCP编程 服务端配置过程 socket():创建一个socket setsockopt():设置socket属性 bind():绑定IP地址、端口等信息到socket类上 listen():开启监听 accept():接收来自客户端的连接 收发数据:send()、recv()、read()、write() 关闭网络连接 关闭监听 3.TCP编程 客户端配置过程 socket():创建一个socket setsockopt():设置socket属性,可选 bind():绑定IP地址、端口等信息到socket上 recvfrom():循环接收数据 关闭网络连接 4.UDP编程 客户端配置过程 socket():创建一个socket setsockopt():设置socket属性,可选 bind():绑定IP地址、端口等信息到socket上 设置对方的IP地址和端口等属性 sendto():发送数据 关闭网络连接 SAL套接字抽象层 SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。\n1.SAL组件主要功能特点: 抽象、统一多种网络协议栈接口 提供Socket层面的TLS加密传输特性 支持标准 BSD Socket API 统一的FD管理,便于使用read/write poll/select来操作网络功能 2.SAL网络框架 应用层:提供一套标准BSD Socket API1。如socket、connect等函数,用于系统中大部分网络开发应用。 SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。 netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。 协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的轻型TCP/IP协议栈lwip以及RT-Thread自主研发的AT Socket网络功能实现等。 3.工作原理 SAL组件工作原理的介绍主要分为如下两部分:\n多协议栈接入与接口函数统一抽象功能 SAL TLS加密传输功能 4.多协议接入与接口函数统一抽象功能 由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。\n目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)2。\n1 int socket(int domain, int type, int protocol); 为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:主协议簇类型和次协议簇类型,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。\n具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。\n目前系统支持协议簇类型如下:\n1 2 3 LWIP协议栈:family = AF_INET、sec_family = AF_INET AT Socket协议栈:family = AF_AT、sec_family = AF_INET WIZnet硬件 TCP/IP协议栈:family = AF_WIZ SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:\nconnect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理; sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数; lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 /* SAL 组件为应用层提供的标准 BSD Socket API */ int connect(int s, const struct sockaddr *name, socklen_t namelen) { /* 获取 SAL 套接字描述符 */ int socket = dfs_net_getsocket(s); /* 通过 SAL 套接字描述符执行 sal_connect 函数 */ return sal_connect(socket, name, namelen); } /* SAL 组件抽象函数接口实现 */ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) { struct sal_socket *sock; struct sal_proto_family *pf; int ret; /* 检查 SAL socket 结构体是否正常 */ SAL_SOCKET_OBJ_GET(sock, socket); /* 检查当前 socket 网络连接状态是否正常 */ SAL_NETDEV_IS_COMMONICABLE(sock-\u0026gt;netdev); /* 检查当前 socket 对应的底层 operation 函数是否正常 */ SAL_NETDEV_SOCKETOPS_VALID(sock-\u0026gt;netdev, pf, connect); /* 执行底层注册的 connect operation 函数 */ ret = pf-\u0026gt;skt_ops-\u0026gt;connect((int) sock-\u0026gt;user_data, name, namelen); #ifdef SAL_USING_TLS if (ret \u0026gt;= 0 \u0026amp;\u0026amp; SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect)) { if (proto_tls-\u0026gt;ops-\u0026gt;connect(sock-\u0026gt;user_data_tls) \u0026lt; 0) { return -1; } return ret; } #endif return ret; } /* lwIP 协议栈函数底层 connect 函数实现 */ int lwip_connect(int socket, const struct sockaddr *name, socklen_t namelen) { ... } 5.SAL TLS加密传输功能 在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。\nTLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。3\n对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。\n使用流程:\n配置开启任意网络协议栈支持(如LWIP协议栈) 配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式) 配置开启SAL_TLS功能支持 配置完成后,需要在socket创建时传入的potocol类型是使用PROTOCOL_TLS或者PROTOCOL_DTLS,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。\n示例如下,参考RT-Threda文档中心:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;sys/socket.h\u0026gt; #include \u0026lt;netdb.h\u0026gt; /* RT-Thread 官网,支持 TLS 功能 */ #define SAL_TLS_HOST \u0026#34;www.rt-thread.org\u0026#34; #define SAL_TLS_PORT 443 #define SAL_TLS_BUFSZ 1024 static const char *send_data = \u0026#34;GET /download/rt-thread.txt HTTP/1.1\\r\\n\u0026#34; \u0026#34;Host: www.rt-thread.org\\r\\n\u0026#34; \u0026#34;User-Agent: rtthread/4.0.1 rtt\\r\\n\\r\\n\u0026#34;; void sal_tls_test(void) { int ret, i; char *recv_data; struct hostent *host; int sock = -1, bytes_received; struct sockaddr_in server_addr; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(SAL_TLS_HOST); recv_data = rt_calloc(1, SAL_TLS_BUFSZ); if (recv_data == RT_NULL) { rt_kprintf(\u0026#34;No memory\\n\u0026#34;); return; } /* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, PROTOCOL_TLS)) \u0026lt; 0) { rt_kprintf(\u0026#34;Socket error\\n\u0026#34;); goto __exit; } /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SAL_TLS_PORT); server_addr.sin_addr = *((struct in_addr *)host-\u0026gt;h_addr); rt_memset(\u0026amp;(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); if (connect(sock, (struct sockaddr *)\u0026amp;server_addr, sizeof(struct sockaddr)) \u0026lt; 0) { rt_kprintf(\u0026#34;Connect fail!\\n\u0026#34;); goto __exit; } /* 发送数据到 socket 连接 */ ret = send(sock, send_data, strlen(send_data), 0); if (ret \u0026lt;= 0) { rt_kprintf(\u0026#34;send error,close the socket.\\n\u0026#34;); goto __exit; } /* 接收并打印响应的数据,使用加密数据传输 */ bytes_received = recv(sock, recv_data, SAL_TLS_BUFSZ - 1, 0); if (bytes_received \u0026lt;= 0) { rt_kprintf(\u0026#34;received error,close the socket.\\n\u0026#34;); goto __exit; } rt_kprintf(\u0026#34;recv data:\\n\u0026#34;); for (i = 0; i \u0026lt; bytes_received; i++) { rt_kprintf(\u0026#34;%c\u0026#34;, recv_data[i]); } __exit: if (recv_data) rt_free(recv_data); if (sock \u0026gt;= 0) closesocket(sock); } #ifdef FINSH_USING_MSH #include \u0026lt;finsh.h\u0026gt; MSH_CMD_EXPORT(sal_tls_test, SAL TLS function test); #endif /* FINSH_USING_MSH */ BSD Socket API 1.创建套接字(socket) 为通信创建一个端点并返回一个文件描述符\n1 int socket(int domain, int type, int protocol); domain:确定协议簇 type:数据类型 protocol:协议 1 2 3 # domain / 协议族类型 AF_INET\t# IPv4 协议族 AF_INET6\t# IPv6 协议族 1 2 3 4 5 # type / 协议类型 /* Socket protocol types (1:TCP/2:UDP/3:RAW) */ #define SOCK_STREAM 1 #define SOCK_DGRAM 2 #define SOCK_RAW 3 2.绑定套接字(bind) 当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。\n1 int bind(int s, const struct sockaddr *name, socklen_t namelen); s:代表socket的文件描述符 name:指向sockaddr结构体的指针,代表要绑定的地址 namelen:是sockaddr结构体的大小 附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。\n来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;arpa/inet.h\u0026gt; #include \u0026lt;netdev.h\u0026gt; #define SERVER_HOST \u0026#34;192.168.1.123\u0026#34; #define SERVER_PORT 1234 static int bing_test(int argc, char **argv) { struct sockaddr_in client_addr; struct sockaddr_in server_addr; struct netdev *netdev = RT_NULL; int sockfd = -1; if (argc != 2) { rt_kprintf(\u0026#34;bind_test [netdev_name] --bind network interface device by name.\\n\u0026#34;); return -RT_ERROR; } /* 通过名称获取 netdev 网卡对象 */ netdev = netdev_get_by_name(argv[1]); if (netdev == RT_NULL) { rt_kprintf(\u0026#34;get network interface device(%s) failed.\\n\u0026#34;, argv[1]); return -RT_ERROR; } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) \u0026lt; 0) { rt_kprintf(\u0026#34;Socket create failed.\\n\u0026#34;); return -RT_ERROR; } /* 初始化需要绑定的客户端地址 */ client_addr.sin_family = AF_INET; client_addr.sin_port = htons(8080); /* 获取网卡对象中 IP 地址信息 */ client_addr.sin_addr.s_addr = netdev-\u0026gt;ip_addr.addr; rt_memset(\u0026amp;(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero)); if (bind(sockfd, (struct sockaddr *)\u0026amp;client_addr, sizeof(struct sockaddr)) \u0026lt; 0) { rt_kprintf(\u0026#34;socket bind failed.\\n\u0026#34;); closesocket(sockfd); return -RT_ERROR; } rt_kprintf(\u0026#34;socket bind network interface device(%s) success!\\n\u0026#34;, netdev-\u0026gt;name); /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = inet_addr(SERVER_HOST); rt_memset(\u0026amp;(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 连接到服务端 */ if (connect(sockfd, (struct sockaddr *)\u0026amp;server_addr, sizeof(struct sockaddr)) \u0026lt; 0) { rt_kprintf(\u0026#34;socket connect failed!\\n\u0026#34;); closesocket(sockfd); return -RT_ERROR; } else { rt_kprintf(\u0026#34;socket connect success!\\n\u0026#34;); } /* 关闭连接 */ closesocket(sockfd); return RT_EOK; } #ifdef FINSH_USING_MSH #include \u0026lt;finsh.h\u0026gt; MSH_CMD_EXPORT(bing_test, bind network interface device test); #endif /* FINSH_USING_MSH */ 3.监听套接字(listen) 当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。\n1 int listen(int s, int backlog); sockfd:代表socket的文件描述符 backlog:一个整数,表示一次能够等待的最大连接数目。 4.接收连接(accept) 当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。\n1 int accept(int s, struct sockaddr *addr, socklen_t *addrlen); s:监听的套接字描述符 addr:指向sockaddr结构体的指针,服务器地址信息 addrlen:sockaddr结构体的大小 5.建立连接(connect) 该函数用于建立与指定 socket 的连接。\n1 int connect(int s, const struct sockaddr *name, socklen_t namelen); s:套接字描述符 name:服务器地址信息 namelen:服务器地址结构体长度 6.TCP数据发送(send) 该函数常用于 TCP 连接发送数据。\n1 int send(int s, const void *dataptr, size_t size, int flags); s:套接字描述符 dataptr:发送的数据指针 size:发送的数据长度 flags:标志,一般为 0 7.TCP数据接收(recv) 该函数用于TCP连接接收数据。\n1 int recv(int s, void *mem, size_t len, int flags); s:套接字描述符 mem:接收的数据指针 len:接收的数据长度 flags:标志,一般为0 8.UDP数据发送(sendto) 该函数用于UDP连接发送数据。\n1 int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); S:套接字描述符 dataptr:发送的数据指针 size:发送的数据长度 flags:标志,一般为0 to:目标结构体指针 tolen:目标地址结构体长度 9.UDP数据接收(recfrom) 该函数用于UDP连接发送数据。\n1 int recvfrom(int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); S:套接字描述符 mem:接收的数据指针 len:接收的数据长度 flags:标志,一般为0 from:接收地址结构体指针 fromlen:接收地址结构体长度 SAL网络协议栈接入方式 网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 /* network interface socket opreations */ struct sal_socket_ops { int (*socket) (int domain, int type, int protocol); int (*closesocket)(int s); int (*bind) (int s, const struct sockaddr *name, socklen_t namelen); int (*listen) (int s, int backlog); int (*connect) (int s, const struct sockaddr *name, socklen_t namelen); int (*accept) (int s, struct sockaddr *addr, socklen_t *addrlen); int (*sendto) (int s, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); int (*recvfrom) (int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); int (*getsockopt) (int s, int level, int optname, void *optval, socklen_t *optlen); int (*setsockopt) (int s, int level, int optname, const void *optval, socklen_t optlen); int (*shutdown) (int s, int how); int (*getpeername)(int s, struct sockaddr *name, socklen_t *namelen); int (*getsockname)(int s, struct sockaddr *name, socklen_t *namelen); int (*ioctlsocket)(int s, long cmd, void *arg); #ifdef SAL_USING_POSIX int (*poll) (struct dfs_fd *file, struct rt_pollreq *req); #endif }; /* sal network database name resolving */ struct sal_netdb_ops { struct hostent* (*gethostbyname) (const char *name); int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); int (*getaddrinfo) (const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); void (*freeaddrinfo) (struct addrinfo *ai); }; /* 协议簇结构体定义 */ struct sal_proto_family { int family; /* primary protocol families type */ int sec_family; /* secondary protocol families type */ const struct sal_socket_ops *skt_ops; /* socket opreations */ const struct sal_netdb_ops *netdb_ops; /* network database opreations */ }; family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。 sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。 skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。 netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。 附录 伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的抽象标准。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nWIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将TCP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2023-04-12T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover_hua7cb33b7b29a8628d474f30421ed1ce5_1481943_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/","title":"RT-Thread网络框架:BSD网络接口\u0026SAL套接字抽象层"},{"content":"Github同步Gitee镜像仓库自动化脚本 前言 在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。\n什么是Hub Mirror Action? 1.介绍 Hub Mirror Action是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。\n2.用法 1 2 3 4 5 6 7 8 9 10 11 steps: - name: Mirror the Github organization repos to Gitee. uses: Yikun/hub-mirror-action@master with: src: github/kunpengcompute dst: gitee/kunpengcompute dst_key: ${{ secrets.GITEE_PRIVATE_KEY }} dst_token: ${{ secrets.GITEE_TOKEN }} account_type: org # src_account_type: org # dst_account_type: org 附:详细使用案例请查看官方仓库 https://github.com/Yikun/hub-mirror-action\n配置步骤 1.生成密钥对 我们先在本地使用git命令行打开终端,输入如下命令:\n1 ssh-keygen -t rsa -f ~/Documents/ssh-key/id_rsa 注:请确保文件夹~/Documents/ssh-key/存在,当然你也可以选择放置在其他地方\n过程中一路回车即可,注意不要设置密码。\n2.GitHub私钥配置 首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。\n依次点击Settings-\u0026gt;Secrets and variables-\u0026gt;Actions\n点击New respository secret,创建一个名为GITEE_PRIVATE_KEY的secret,值为我们之前生成的密钥对中的私钥(id_rsa)\n3.Gitee公钥配置 我们打开Gitee账号,进入Settings-\u0026gt;安全设置-\u0026gt;SSH公钥\n添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)\n4.Gitee生成私人令牌 令牌名称随意,同时复制生成的令牌值。\n5.Github绑定Gitee令牌 依次点击Settings-\u0026gt;Secrets and variables-\u0026gt;Actions\n点击New respository secret,创建一个名为GITEE_TOKEN的secret,值为Gitee生成的令牌值\n6.编写CI脚本 将ci_bot仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:\n1 2 3 4 .ci_bot/ |——.github |——workflows |——Sync.yml 在Sync.yml文件中,添加以下代码:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 name: Sync Github Repos To Gitee on: [ push, delete, create ] jobs: build: runs-on: ubuntu-latest steps: - name: Sync Github Repos To Gitee # 名字随便起 uses: Yikun/hub-mirror-action@master # 使用Yikun/hub-mirror-action with: src: github/kurisaW # 源端账户名(github) dst: gitee/kurisaW # 目的端账户名(gitee) dst_key: ${{ secrets.GITEE_PRIVATE_KEY }} # SSH密钥对中的私钥 dst_token: ${{ secrets.GITEE_TOKEN }} # Gitee账户的私人令牌 account_type: user # 账户类型 clone_style: \u0026#34;https\u0026#34; # 使用https方式进行clone,也可以使用ssh debug: true # 启用后会显示所有执行命令 force_update: true # 启用后,强制同步,即强制覆盖目的端仓库 static_list: \u0026#34;kurisaW_docs\u0026#34; # 静态同步列表,在此填写需要同步的仓库名称,可填写多个 timeout: \u0026#39;600s\u0026#39; # git超时设置,超时后会自动重试git操作 保存退出后,将本次修改push到远端仓库。\n查看Action运行情况:\n7.多仓库同步推送 如果你想同时同步多个仓库,只需要完成如下修改\n1 static_list 默认为\u0026#39;\u0026#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。 8.定时运行脚本 为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:\n修改Sync.yml文件:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 name: Sync Github Repos To Gitee on: schedule: - cron: \u0026#39;0 0 * * *\u0026#39; push: branches: [ main ] delete: branches: [ main ] create: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - name: Sync Github Repos To Gitee # 名字随便起 uses: Yikun/hub-mirror-action@master # 使用Yikun/hub-mirror-action with: src: github/kurisaW # 源端账户名(github) dst: gitee/kurisaW # 目的端账户名(gitee) dst_key: ${{ secrets.GITEE_PRIVATE_KEY }} # SSH密钥对中的私钥 dst_token: ${{ secrets.GITEE_TOKEN }} # Gitee账户的私人令牌 account_type: user # 账户类型 clone_style: \u0026#34;https\u0026#34; # 使用https方式进行clone,也可以使用ssh debug: true # 启用后会显示所有执行命令 force_update: true # 启用后,强制同步,即强制覆盖目的端仓库 static_list: \u0026#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io\u0026#34; # 静态同步列表,在此填写需要同步的仓库名称,可填写多个 timeout: \u0026#39;600s\u0026#39; # git超时设置,超时后会自动重试git操作 也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。\n总结 通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。\n","date":"2023-04-11T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover_hu988a92fc47be5a32e45d6a6ece551f64_92962_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/","title":"Github同步Gitee镜像仓库自动化脚本"},{"content":"OSI七层模型 七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。\n1.物理层 建立、维护、断开物理连接。(由底层网络定义协议)\n机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。\n应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。\n2.数据链路层 建立逻辑连接、进行硬件地址寻址、差错校验等功能。(由底层网络定义协议)\n将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 物理寻址、同时将原始比特流转变为逻辑传输线路 地址解析协议:ARP、PARP(反向地址转换协议)\n3.网络层 进行逻辑地址寻址,实现不同网络之间的路径选择。\n控制子网的运行,如逻辑编址、分组传输、路由选择 协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) 安全协议、路由协议(vrrp虚拟路由冗余)\n4.传输层 定义传输数据的协议端口号,以及流控和差错校验。 接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层\n5.会话层 建立、管理、终止会话。(在五层模型里面已经合并到了应用层)\n不同机器上的用户之间建立及管理会话 对应主机进程,指本地主机与远程主机正在进行的会话 安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)\n6.表示层 数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)\n信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] 如LPP(轻量级表示协议)\n7.应用层 网络服务与最终用户的一个接口\n各种应用程序协议: HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)\nTCP/IP 四层模型 TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。\nTCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示\n1.应用层 应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。\n应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次 对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议 应用层还能加密、解密、格式化数据 应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源 2.传输层 作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用\n3.网络层 网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能\n4.网络接口层 在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路\n","date":"2023-04-10T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover_hua119e4204b5ed27e667ee608d4609605_260211_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/","title":"【网络编程】OSI七层模型\u0026TCPIP四层模型"},{"content":" 来源:转自:WireShark 抓包使用教程\u0026ndash;详细\n前言 Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:\n1、Wireshark软件下载和安装以及Wireshark主界面介绍。\n2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。\n3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。\nWireshark软件安装 软件下载路径:wireshark官网。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。\n如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:win10pcap兼容性安装包\nWireshark 开始抓包示例 先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。\n1、打开wireshark 2.6.5,主界面如下:\n2、选择菜单栏上Capture -\u0026gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。\n3、wireshark启动后,wireshark处于抓包状态中。\n4、执行需要抓包的操作,如ping www.baidu.com。\n5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。\n5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。\nWireshakr抓包界面 说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --\u0026gt; Coloring Rules。如下所示\nWireShark 主要分为这几个界面\n1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --\u0026gt; Display Filters。\n2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。\n3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为\n(1)Frame: 物理层的数据帧概况\n(2)Ethernet II: 数据链路层以太网帧头部信息\n(3)Internet Protocol Version 4: 互联网层IP包头部信息\n(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP\n(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议\nTCP包的具体内容\n从下图可以看到wireshark捕获到的TCP包中的每个字段。\n4. Dissector Pane(数据包字节区)。\nWireshark过滤器设置 初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。\n(1)抓包过滤器\n捕获过滤器的菜单栏路径为Capture --\u0026gt; Capture Filters。用于在抓取数据包前设置。\n如何使用?可以在抓取数据包前设置如下。\nip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:\n(2)显示过滤器\n显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下\n执行ping www.huawei.com获取的数据包列表如下\n观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。\n上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。\nwireshark过滤器表达式的规则\n1、抓包过滤器语法和实例\n抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(\u0026amp;\u0026amp; 与、|| 或、!非)\n(1)协议过滤\n比较简单,直接在抓包过滤框中直接输入协议名即可。\nTCP,只显示TCP协议的数据包列表\nHTTP,只查看HTTP协议的数据包列表\nICMP,只显示ICMP协议的数据包列表\n(2)IP过滤\nhost 192.168.1.104\nsrc host 192.168.1.104\ndst host 192.168.1.104\n(3)端口过滤\nport 80\nsrc port 80\ndst port 80\n(4)逻辑运算符\u0026amp;\u0026amp; 与、|| 或、!非\nsrc host 192.168.1.104 \u0026amp;\u0026amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包\nhost 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包\n!broadcast 不抓取广播数据包\n2、显示过滤器语法和实例\n(1)比较操作符\n比较操作符有== 等于、!= 不等于、\u0026gt; 大于、\u0026lt; 小于、\u0026gt;= 大于等于、\u0026lt;=小于等于。\n(2)协议过滤\n比较简单,直接在Filter框中直接输入协议名即可。注意:协议名称需要输入小写。\ntcp,只显示TCP协议的数据包列表\nhttp,只查看HTTP协议的数据包列表\nicmp,只显示ICMP协议的数据包列表\n(3) ip过滤\nip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表\nip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表\nip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表\n(4)端口过滤\ntcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。\ntcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。\ntcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。\n(5) Http模式过滤\nhttp.request.method==\u0026ldquo;GET\u0026rdquo;, 只显示HTTP GET方法的。\n(6)逻辑运算符为 and/or/not\n过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp\n(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下\n右键单击选中后出现如下界面\n选中Select后在过滤器中显示如下\n后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含\u0026quot;abcd\u0026quot;内容的数据流。包含的关键词是contains 后面跟上内容。\n看到这, 基本上对wireshak有了初步了解。\nWireshark抓包分析TCP三次握手 (1)TCP三次握手连接建立过程\nStep1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;\nStep2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;\nStep3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。\n(2)wireshark抓包获取访问指定服务端数据包\nStep1:启动wireshark抓包,打开浏览器输入www.huawei.com。\nStep2:使用ping www.huawei.com获取IP。\nStep3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183\n图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。\n第一次握手数据包\n客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。\n数据包的关键属性如下:\nSYN :标志位,表示请求建立连接\nSeq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据\nAck =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据\n第二次握手的数据包\n服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图\n数据包的关键属性如下:\n[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK\nSeq = 0 :初始建立值为0,表示当前还没有发送数据\nAck = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)\n第三次握手的数据包\n客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:\n数据包的关键属性如下:\nACK :标志位,表示已经收到记录\nSeq = 1 :表示当前已经发送1个数据\nAck = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。\n就这样通过了TCP三次握手,建立了连接。开始进行数据交互\n下面针对数据交互过程的数据包进行一些说明:\n数据包的关键属性说明\nSeq: 1\nAck: 1: 说明现在共收到1字节数据\nSeq: 1\nAck: 951: 说明现在服务端共收到951字节数据\n在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下\n其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。\nWireshark分析常用操作 调整数据包列表中时间戳显示格式。调整方法为View --\u0026gt;Time Display Format --\u0026gt; Date and Time of Day。调整后格式如下:\n","date":"2023-04-10T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover_hu042cdab30ea052232a927d02c15faadc_94256_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/","title":"Wireshark网络抓包教程"},{"content":"1.RT-Thread版本信息 1 2 3 4 5 6 7 /* RT-Thread version information */ #define RT_VERSION 4 /**\u0026lt; major version number */ #define RT_SUBVERSION 1 /**\u0026lt; minor version number */ #define RT_REVISION 1 /**\u0026lt; revise version number */ /* RT-Thread version */ #define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION) 使用方法:可用于bsp指定RT-Thread版本\n例如:\n1 2 3 #if (RTTHREAD_VERSION \u0026gt;= RT_VERSION_CHECK(4, 1, 0) */ #define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \\ (minor * 100) + revise) 2.RT-Thrad基础数据类型定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 /* RT-Thread basic data type definitions */ #ifndef RT_USING_ARCH_DATA_TYPE\t/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */ #ifdef RT_USING_LIBC\t/* 用于控制是否使用标准C库函数 */ typedef int8_t rt_int8_t; /**\u0026lt; 8bit integer type */ typedef int16_t rt_int16_t; /**\u0026lt; 16bit integer type */ typedef int32_t rt_int32_t; /**\u0026lt; 32bit integer type */ typedef uint8_t rt_uint8_t; /**\u0026lt; 8bit unsigned integer type */ typedef uint16_t rt_uint16_t; /**\u0026lt; 16bit unsigned integer type */ typedef uint32_t rt_uint32_t; /**\u0026lt; 32bit unsigned integer type */ typedef int64_t rt_int64_t; /**\u0026lt; 64bit integer type */ typedef uint64_t rt_uint64_t; /**\u0026lt; 64bit unsigned integer type */ typedef size_t rt_size_t; /**\u0026lt; Type for size number */ #else typedef signed char rt_int8_t; /**\u0026lt; 8bit integer type */ typedef signed short rt_int16_t; /**\u0026lt; 16bit integer type */ typedef signed int rt_int32_t; /**\u0026lt; 32bit integer type */ typedef unsigned char rt_uint8_t; /**\u0026lt; 8bit unsigned integer type */ typedef unsigned short rt_uint16_t; /**\u0026lt; 16bit unsigned integer type */ typedef unsigned int rt_uint32_t; /**\u0026lt; 32bit unsigned integer type */ #ifdef ARCH_CPU_64BIT\t/* 判断当前程序运行的CPU架构是否为64位 */ typedef signed long rt_int64_t; /**\u0026lt; 64bit integer type */ typedef unsigned long rt_uint64_t; /**\u0026lt; 64bit unsigned integer type */ typedef unsigned long rt_size_t; /**\u0026lt; Type for size number */ #else typedef signed long long rt_int64_t; /**\u0026lt; 64bit integer type */ typedef unsigned long long rt_uint64_t; /**\u0026lt; 64bit unsigned integer type */ typedef unsigned int rt_size_t; /**\u0026lt; Type for size number */ #endif /* ARCH_CPU_64BIT */ #endif /* RT_USING_LIBC */ #endif /* RT_USING_ARCH_DATA_TYPE */ typedef int rt_bool_t; /**\u0026lt; boolean type */ typedef long rt_base_t; /**\u0026lt; Nbit CPU related date type */ typedef unsigned long rt_ubase_t; /**\u0026lt; Nbit unsigned CPU related data type */ typedef rt_base_t rt_err_t; /**\u0026lt; Type for error number */ typedef rt_uint32_t rt_time_t; /**\u0026lt; Type for time stamp */ typedef rt_uint32_t rt_tick_t; /**\u0026lt; Type for tick count */ typedef rt_base_t rt_flag_t; /**\u0026lt; Type for flags */ typedef rt_ubase_t rt_dev_t; /**\u0026lt; Type for device */ typedef rt_base_t rt_off_t; /**\u0026lt; Type for offset */ /* boolean type definitions */ #define RT_TRUE 1 /**\u0026lt; boolean true */ #define RT_FALSE 0 /**\u0026lt; boolean fails */ /* null pointer definition */ #define RT_NULL 0 rt_base_t:为了使代码可以在不同的CPU上移植并保持向后兼容性。long类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用rt_base_t代替long可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)\nrt_err_t:代表错误码的数据类型,这里使用了之前定义的rt_base_t作为它的别名。\nrt_time_t:代表时间戳的数据类型,这里使用了rt_uint32_t作为它的别名。rt_uint32_t是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。\nrt_tick_t:代表系统时钟节拍计数的数据类型,这里也使用了rt_uint32_t作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对rt_tick_t进行递增操作,从而实现对时间的计数。\nrt_flag_t:代表标志位的数据类型,这里使用了之前定义的rt_base_t作为它的别名。\nrt_dev_t:代表设备号的数据类型,这里使用了rt_ubase_t作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。\nrt_off_t:代表偏移量的数据类型,这里也使用了之前定义的rt_base_t作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。\n3.RT-Thread基本数据类型的范围 1 2 3 4 5 6 7 8 9 10 /* maximum value of base type */ #ifdef RT_USING_LIBC #define RT_UINT8_MAX UINT8_MAX /**\u0026lt; Maximum number of UINT8 */ #define RT_UINT16_MAX UINT16_MAX /**\u0026lt; Maximum number of UINT16 */ #define RT_UINT32_MAX UINT32_MAX /**\u0026lt; Maximum number of UINT32 */ #else #define RT_UINT8_MAX 0xff /**\u0026lt; Maximum number of UINT8 */ #define RT_UINT16_MAX 0xffff /**\u0026lt; Maximum number of UINT16 */ #define RT_UINT32_MAX 0xffffffff /**\u0026lt; Maximum number of UINT32 */ #endif /* RT_USING_LIBC */ 附:此处的UINT8_MAX、UINT16_MAX、UINT32_MAX为编译器预定的宏定义\n4.RT-Thread系统滴答时钟最大计数值 1 #define RT_TICK_MAX RT_UINT32_MAX /**\u0026lt; Maximum number of tick */ 5.RT-Thread IPC数据类型范围 1 2 3 4 5 6 /* maximum value of ipc type */ #define RT_SEM_VALUE_MAX RT_UINT16_MAX /**\u0026lt; Maximum number of semaphore .value */ #define RT_MUTEX_VALUE_MAX RT_UINT16_MAX /**\u0026lt; Maximum number of mutex .value */ #define RT_MUTEX_HOLD_MAX RT_UINT8_MAX /**\u0026lt; Maximum number of mutex .hold */ #define RT_MB_ENTRY_MAX RT_UINT16_MAX /**\u0026lt; Maximum number of mailbox .entry */ #define RT_MQ_ENTRY_MAX RT_UINT16_MAX /**\u0026lt; Maximum number of message queue .entry */ 6.RT-Thread避免未使用变量警告 1 #define RT_UNUSED(x) ((void)x) **该宏定义表示将变量x强制转换为void类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **\n下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。\n该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。\n在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。\n这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include \u0026lt;stdlib.h\u0026gt; int cmp(const void *a, const void *b) { /* sort code */ } int main() { int arr[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; qsort(arr, 10, sizeof(int), cmp); // 必须传递一个void*类型参数 return 0; } int cmp(const void *a, const void *b) { RT_UNUSED(a); // 标记参数未使用 RT_UNUSED(b); // 标记参数未使用 return 0; } 这样就可以避免编译器报“未使用变量a/b”的警告了。\n7.编译器相关定义 1 2 3 4 5 6 7 /* Compiler Related Definitions */ #if defined(__ARMCC_VERSION) /* ARM Compiler */ #define RT_SECTION(x) __attribute__((section(x))) #define RT_USED __attribute__((used)) #define ALIGN(n) __attribute__((aligned(n))) #define RT_WEAK __attribute__((weak)) #define rt_inline static __inline RT_SECTION(x):表示将所修饰的数据/函数放置在指定的section中,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。 RT_USED:表示告诉编译器保留所修饰的数据/函数,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。 ALIGN(n):表示将所修饰的数据/函数按照n字节对齐,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。 RT_WEAK:表示将所修饰的数据/函数标记为弱引用,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。 rt_inline:表示将所修饰的函数定义为静态内联函数,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。 8.编译器相关定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 /* Compiler Related Definitions */ #if defined(__ARMCC_VERSION) /* ARM Compiler */ #define RT_SECTION(x) __attribute__((section(x))) #define RT_USED __attribute__((used)) #define ALIGN(n) __attribute__((aligned(n))) #define RT_WEAK __attribute__((weak)) #define rt_inline static __inline /* module compiling */ #ifdef RT_USING_MODULE #define RTT_API __declspec(dllimport) #else #define RTT_API __declspec(dllexport) #endif /* RT_USING_MODULE */ #elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ #define RT_SECTION(x) @ x #define RT_USED __root #define PRAGMA(x) _Pragma(#x) #define ALIGN(n) PRAGMA(data_alignment=n) #define RT_WEAK __weak #define rt_inline static inline #define RTT_API #elif defined (__GNUC__) /* GNU GCC Compiler */ #ifndef RT_USING_LIBC /* the version of GNU GCC must be greater than 4.x */ typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #endif /* RT_USING_LIBC */ #define RT_SECTION(x) __attribute__((section(x))) #define RT_USED __attribute__((used)) #define ALIGN(n) __attribute__((aligned(n))) #define RT_WEAK __attribute__((weak)) #define rt_inline static __inline #define RTT_API #elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */ #define RT_SECTION(x) __attribute__((section(x))) #define RT_USED __attribute__((used)) #define ALIGN(n) __attribute__((aligned(n))) #define RT_WEAK __attribute__((weak)) #define rt_inline static inline #define RTT_API #elif defined (_MSC_VER) #define RT_SECTION(x) #define RT_USED #define ALIGN(n) __declspec(align(n)) #define RT_WEAK #define rt_inline static __inline #define RTT_API #elif defined (__TI_COMPILER_VERSION__) /* The way that TI compiler set section is different from other(at least * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more * details. */ #define RT_SECTION(x) #define RT_USED #define PRAGMA(x) _Pragma(#x) #define ALIGN(n) #define RT_WEAK #define rt_inline static inline #define RTT_API #elif defined (__TASKING__) #define RT_SECTION(x) __attribute__((section(x))) #define RT_USED __attribute__((used, protect)) #define PRAGMA(x) _Pragma(#x) #define ALIGN(n) __attribute__((__align(n))) #define RT_WEAK __attribute__((weak)) #define rt_inline static inline #define RTT_API #else #error not supported tool chain #endif /* __ARMCC_VERSION */ typedef __builtin_va_list __gnuc_va_list: 定义了一个新类型__gnuc_va_list,并使用 __builtin_va_list 进行初始化。__builtin_va_list 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 __builtin_va_list 类型来实现可变参数列表。 typedef __gnuc_va_list va_list: 定义了一个名为va_list的新类型,并将其重命名为__gnuc_va_list。 #define va_start(v,l) __builtin_va_start(v,l): 将 va_start() 重命名为 __builtin_va_start(),从而能够使用 GCC 内建的函数 __builtin_va_start() 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。 #define va_end(v) __builtin_va_end(v): 将 va_end() 重命名为 __builtin_va_end(),从而能够使用 GCC 内建的函数 __builtin_va_end() 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。 #define va_arg(v,l) __builtin_va_arg(v,l): 将 va_arg() 重命名为 __builtin_va_arg(),并使用 GCC 内建的函数 __builtin_va_arg() 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。 #define PRAGMA(x) _Pragma(#x):将参数x转化为字符串并使用_Pragma()将其作为编译指令执行。_Pragma是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而#pragma则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。 9.RT-Thread错误码定义 1 2 3 4 5 6 7 8 9 10 11 12 /* RT-Thread error code definitions */ #define RT_EOK 0 /**\u0026lt; There is no error */ #define RT_ERROR 1 /**\u0026lt; A generic error happens */ #define RT_ETIMEOUT 2 /**\u0026lt; Timed out */ #define RT_EFULL 3 /**\u0026lt; The resource is full */ #define RT_EEMPTY 4 /**\u0026lt; The resource is empty */ #define RT_ENOMEM 5 /**\u0026lt; No memory */ #define RT_ENOSYS 6 /**\u0026lt; No system */ #define RT_EBUSY 7 /**\u0026lt; Busy */ #define RT_EIO 8 /**\u0026lt; IO error */ #define RT_EINTR 9 /**\u0026lt; Interrupted system call */ #define RT_EINVAL 10 /**\u0026lt; Invalid argument */ RT_EOK:表示没有错误。 RT_ERROR:表示发生了一般性的错误。 RT_ETIMEOUT:表示超时错误。 RT_EFULL:表示资源已满。 RT_EEMPTY:表示资源为空。 RT_ENOMEM:表示内存不足。 RT_ENOSYS:表示没有该系统。 RT_EBUSY:表示忙碌。 RT_EIO:表示输入/输出错误。 RT_EINTR:表示中断的系统调用。 RT_EINVAL:表示无效的参数。 ","date":"2023-04-09T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/cover_hub6a66fbbe5f509b396b5c62bec10766b_210091_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/","title":"RT-Thread内核宏定义详解(rtdef.h)"},{"content":"一、BearPi-HM Micro 开发板介绍 BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。\n二、Linux镜像下载 下载官方提供镜像(任选一种方式下载)\nUbuntu20.04(大小8G)下载地址(百度云):https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA 提取码:1234 Ubuntu18.04(大小4.8G)下载地址(百度云):https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ 提取码:1234 三、BearPi-HM Micro编译环境配置 在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置\n1.首先添加如下镜像源 1 vi /etc/apt/source.list 1 2 3 4 5 6 7 8 9 10 11 # 添加中科大源 deb https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse 2.更新镜像源 1 sudo apt-get update 3.安装依赖库及工具 1 sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi cpio device-tree-compiler net-tools openssh-server git vim openjdk-11-jre-headless 4.安装hb 1 2 # 安装hb命令 python3 -m pip install --user ohos-build==0.4.3 1 2 3 4 5 6 7 8 # 环境变量配置 sudo vim ~/.bashrc # 在.bashrc文件最后一行添加如下代码,并保存退出 export PATH=~/.local/bin:$PATH # 更新环境变量 source ~/.bashrc 5.测试hb是否安装成功 1 hb -h 四、安装mkimage工具 首先解释这个工具的用途:用来制作不压缩或者压缩的多种可启动映象文件。\n1.新建tools目录 1 mkdir ~/tools 2.下载mkimage.stm32工具到~/tools目录,并复制到/home/bearpi/tools/目录下 mkimage.stm32下载地址 提取码:1234 3.修改mkimage.stm32文件权限 1 chmod 777 ~/tools/mkimage.stm32 4.设置环境变量 1 2 3 4 5 6 7 vim ~/.bashrc # 将下面的代码拷贝至.bashrc文件最后,并保存退出 export PATH=~/tools:$PATH # 更新环境变量 source ~/.bashrc 五、bearpi镜像导入VMware 准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-\u0026gt;打开(O),选择我们Linux镜像中的BearPi-HM_Micro_Ubuntu.ovf文件,等待镜像文件的导入,开始登录\n1 2 账户:bearpi 密码:bearpi 首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-\u0026gt;设置-\u0026gt;网络适配器-\u0026gt;NAT模式\n此时打开一个终端,输入ifconfig查看ip\n六、源码获取 1 2 3 4 5 cd /home/bearpi mkdir project \u0026amp;\u0026amp; cd project git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git 七、编译代码 首先进入到项目文件夹中\n1 cd /home/bearpi/project/bearpi-hm_micro_small/ 执行如下命令(普通用户模式终端下):\n1 hb set 出现[OHOS INFO] Input code path: 提示信息后再输入.\n我们选择bearpi-hm_micro后回车\n输入下面的命令,等待下载程序完成\n1 hb build -t notest --tee -f 当出现build success时,即代表编译成功\n八、查看编译出的固件位置 当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: /home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro 其中有以下文件是后面烧录系统需要使用的。\nOHOS_Image.stm32:系统镜像文件 rootfs_vfat.img:根文件系统 userfs_vfat.img:用户文件系统 我们将这三个文件复制到该目录下:/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/,方便后续烧录系统使用\n1 cp -r OHOS_Image.stm32 rootfs_vfat.img userfs_vfat.img /home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/ 九、固件烧录 1.准备工作 CH340驱动 STM32CubeProgramme(v2.4.0+) 2.连接开发板 首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:【Linux系统开发】Ubuntu配置SFTP服务)\n当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。\n我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机\n3.镜像烧录 首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。\n打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。\n点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:Y:\\home\\bearpi\\project\\bearpi-hm_micro_small\\applications\\BearPi\\BearPi-HM_Micro\\tools\\download_img\\flashlayout\\bearpi-hm_micro.tsv)。\n点击Browse按钮,然后选择工程源码下的烧录镜像路径\n点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机\n4.启动系统 将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。\n","date":"2023-04-07T00:00:00Z","image":"https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover_hu7ad68eb49f84d52979d238bd23b98016_1037452_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/","title":"【HarmonyOS】小熊派鸿蒙系统搭建"},{"content":"SFTP介绍 SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)\n安装步骤 1.目标: 在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。\n2.查看Ubuntu系统信息 3.检查是否已安装SFTP 在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:\n1 2 安装openssh-client: sudo apt-get install openssh-client 安装openssh-server: sudo apt-get install openssh-server 这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。\n4.新建用户组SFTP-users,并新建用户SFTP 为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:\n1 2 sudo addgroup sftp-users sudo adduser sftp (这部分会让你新建用户组信息,建议最好截图保存下) 5.给SFTP赋权并新建用户组SSH-users 将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:\n1 sudo usermod -G sftp-users -s /bin/false sftp 创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。\n1 2 sudo addgroup ssh-users sudo usermod -a -G ssh-users bbc2005 6.创建并设置SFTP用户目录 为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: 所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。\n1 2 3 4 5 sudo mkdir /home/sftp_root sudo mkdir /home/sftp_root/shared sudo chown yifang:sftp-users /home/sftp_root/shared sudo chmod 770 /home/sftp_root/shared 7.修改SSH配置文件 在sshd_config文件的最后添加以下内容:\n1 vi /etc/ssh/sshd_config 1 2 3 4 5 6 7 AllowGroups ssh-users sftp-users Match Group sftp-users ChrootDirectory /home/sftp_root AllowTcpForwarding no X11Forwarding no ForceCommand internal-sftp 这些内容的意思是:\n只允许ssh-users和SFTP-users通过SSH访问系统; 针对SFTP-users用户,增加一些额外的设置: 将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件); 禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。 如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。 8.SFTP客户端验证 首先将虚拟机重启:\n1 sudo reboot 在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。\n查看ubuntu网络ip地址\n1 ifconfig zhe\n这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考RaiDrive—将网盘映射为磁盘)\n此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。\n","date":"2023-04-07T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover_hud91d0899887ba9e32d396fd4ea2dabdc_982644_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/","title":"【Linux系统开发】Ubuntu配置SFTP服务"},{"content":" 来源:https://zhuanlan.zhihu.com/p/585079427\n1.芯片行业 目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。\n代表性公司:\n(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等\n(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等\n2.人工智能相关行业 (1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。\n(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等\n3.消费电子行业 消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等\n4.传统汽车行业 传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等\n5.国企和军工 国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。\n6.传统电子电器类 这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等\n7.网络及通信设备 主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等\n","date":"2023-04-03T00:00:00Z","image":"https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/cover_hub3bebb46daa420fb309872f8e1c7f3d2_929086_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/","title":"【资讯】汇总一些嵌入式相关的公司"},{"content":"ARM常用汇编指令 指令名称 作用 EQU 给数字常量设置一个符号名,相当于C语言中的define AREA 汇编一个新的代码段或者数据段 SPACE 分配内存空间 PRESERVE8 当前文件栈需要按照8字节对齐 EXPORT 声明一个符号具有全局属性,可被外部文件使用 DCD 以字为单位分配内存,要求4字节对齐,并要求初始化这些内存 PROC 定义子程序,与ENDP成对使用,表示子程序结束 WEAK 弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便 IMPORT 声明标号来自外部文件,与C语言的EXETERN关键字类似 B 跳转到一个标号 ALIGN 编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便 END 到达文件的末尾,文件结束 IF,ELSE,ENDIF 汇编条件分支语句,与C语言的if else类似 MRS 加载特殊功能寄存器的值到特殊功能寄存器 CBZ 比较,如果结果为0则转移 CBNZ 比较,如果结果非0则转移 LDR 从存储器中加载字到一个寄存器中 LDR[伪指令] 加载一个立即数或者一个地址到一个寄存器中。 LDRH 从存储器中加载半字到一个寄存器中 LDRB 从存储器中加载字节到一个寄存器中 STR 把一个寄存器按字节存储到存储器中 STRH 把一个寄存器的低半字存储到存储器中 STRB 把一个寄存器的低字节存储到存储器中 LDMIA 加载多个字,并且在加载后自增基址寄存器 STMIA 存储多个字,并且在存储后自增基址寄存器 ORR 按位或 BX 直接跳转到由寄存器给定的地址 BL 跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR BLX 跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错 ","date":"2023-03-29T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/cover_hua2b1d1bfe2fa537ec78f40e9845c7606_53779_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/","title":"【经验分享】ARM常用汇编指令"},{"content":"前言 Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 回撤这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而版本管理工具能记录每次的修改,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。\n下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。\n展示帮助信息 1 git help -g The command output as below:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 The common Git guides are: attributes Defining attributes per path cli Git command-line interface and conventions core-tutorial A Git core tutorial for developers cvs-migration Git for CVS users diffcore Tweaking diff output everyday A useful minimum set of commands for Everyday Git glossary A Git Glossary hooks Hooks used by Git ignore Specifies intentionally untracked files to ignore modules Defining submodule properties namespaces Git namespaces repository-layout Git Repository Layout revisions Specifying revisions and ranges for Git tutorial A tutorial introduction to Git tutorial-2 A tutorial introduction to Git: part two workflows An overview of recommended workflows with Git \u0026#39;git help -a\u0026#39; and \u0026#39;git help -g\u0026#39; list available subcommands and some concept guides. See \u0026#39;git help \u0026lt;command\u0026gt;\u0026#39; or \u0026#39;git help \u0026lt;concept\u0026gt;\u0026#39; to read about a specific subcommand or concept. 回到远程仓库的状态 抛弃本地所有的修改,回到远程仓库的状态。\n1 git fetch --all \u0026amp;\u0026amp; git reset --hard origin/master 重设第一个 commit 也就是把所有的改动都重新放回工作区,并清空所有的 commit,这样就可以重新提交第一个 commit 了\n1 git update-ref -d HEAD 查看冲突文件列表 展示工作区的冲突文件列表\n1 git diff --name-only --diff-filter=U 展示工作区和暂存区的不同 输出工作区和暂存区的 different (不同)。\n1 git diff 还可以展示本地仓库中任意两个 commit 之间的文件变动:\n1 git diff \u0026lt;commit-id\u0026gt; \u0026lt;commit-id\u0026gt; 展示暂存区和最近版本的不同 输出暂存区和本地最近的版本 (commit) 的 different (不同)。\n1 git diff --cached 展示暂存区、工作区和最近版本的不同 输出工作区、暂存区 和本地最近的版本 (commit) 的 different (不同)。\n1 git diff HEAD 快速切换到上一个分支 1 git checkout - 删除已经合并到 master 的分支 1 git branch --merged master | grep -v \u0026#39;^\\*\\| master\u0026#39; | xargs -n 1 git branch -d 展示本地分支关联远程仓库的情况 1 git branch -vv 关联远程分支 关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。\n1 git branch -u origin/mybranch 或者在 push 时加上 -u 参数\n1 git push origin/mybranch -u 列出所有远程分支 -r 参数相当于:remote\n1 git branch -r 列出本地和远程分支 -a 参数相当于:all\n1 git branch -a 查看远程分支和本地分支的对应关系 1 git remote show origin 远程删除了分支本地也想删除 1 git remote prune origin 创建并切换到本地分支 1 git checkout -b \u0026lt;branch-name\u0026gt; 从远程分支中创建并切换到本地分支 1 git checkout -b \u0026lt;branch-name\u0026gt; origin/\u0026lt;branch-name\u0026gt; 删除本地分支 1 git branch -d \u0026lt;local-branchname\u0026gt; 删除远程分支 1 git push origin --delete \u0026lt;remote-branchname\u0026gt; 或者\n1 git push origin :\u0026lt;remote-branchname\u0026gt; 重命名本地分支 1 git branch -m \u0026lt;new-branch-name\u0026gt; 查看标签 1 git tag 展示当前分支的最近的 tag\n1 git describe --tags --abbrev=0 查看标签详细信息 1 git tag -ln 本地创建标签 1 git tag \u0026lt;version-number\u0026gt; 默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:\n1 $ git tag -a \u0026lt;version-number\u0026gt; -m \u0026#34;v1.0 发布(描述)\u0026#34; \u0026lt;commit-id\u0026gt; 推送标签到远程仓库 首先要保证本地创建好了标签才可以推送标签到远程仓库:\n1 git push origin \u0026lt;local-version-number\u0026gt; 一次性推送所有标签,同步到远程仓库:\n1 git push origin --tags 删除本地标签 1 git tag -d \u0026lt;tag-name\u0026gt; 删除远程标签 1 git push origin --delete tag \u0026lt;tagname\u0026gt; 切回到某个标签 一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:\n1 git checkout -b branch_name tag_name 放弃工作区的修改 1 git checkout \u0026lt;file-name\u0026gt; 放弃所有修改:\n1 git checkout . 恢复删除的文件 1 2 3 git rev-list -n 1 HEAD -- \u0026lt;file_path\u0026gt; #得到 deleting_commit git checkout \u0026lt;deleting_commit\u0026gt;^ -- \u0026lt;file_path\u0026gt; #回到删除文件 deleting_commit 之前的状态 以新增一个 commit 的方式还原某一个 commit 的修改 1 git revert \u0026lt;commit-id\u0026gt; 回到某个 commit 的状态,并删除后面的 commit 和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit\n1 2 3 4 5 6 7 git reset \u0026lt;commit-id\u0026gt; #默认就是-mixed参数。 git reset --mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。 git reset --soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 git reset --hard \u0026lt;commit-id\u0026gt; #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容 修改上一个 commit 的描述 如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit\n1 git commit --amend 查看 commit 历史 1 git log 查看某段代码是谁写的 blame 的意思为‘责怪’,你懂的。\n1 git blame \u0026lt;file-name\u0026gt; 显示本地更新过 HEAD 的 git 命令记录 每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。\n1 git reflog 修改作者名 1 git commit --amend --author=\u0026#39;Author Name \u0026lt;email@address.com\u0026gt;\u0026#39; 修改远程仓库的 url 1 git remote set-url origin \u0026lt;URL\u0026gt; 增加远程仓库 1 git remote add origin \u0026lt;remote-url\u0026gt; 列出所有远程仓库 1 git remote 查看两个星期内的改动 1 git whatchanged --since=\u0026#39;2 weeks ago\u0026#39; 把 A 分支的某一个 commit,放到 B 分支上 这个过程需要 cherry-pick 命令,参考\n1 git checkout \u0026lt;branch-name\u0026gt; \u0026amp;\u0026amp; git cherry-pick \u0026lt;commit-id\u0026gt; 给 git 命令起别名 简化命令\n1 2 3 4 5 git config --global alias.\u0026lt;handle\u0026gt; \u0026lt;command\u0026gt; 比如:git status 改成 git st,这样可以简化命令 git config --global alias.st status 存储当前的修改,但不用提交 commit 详解可以参考廖雪峰老师的 git 教程\n1 git stash 保存当前状态,包括 untracked 的文件 untracked 文件:新建的文件\n1 git stash -u 展示所有 stashes 1 git stash list 回到某个 stash 的状态 1 git stash apply \u0026lt;stash@{n}\u0026gt; 回到最后一个 stash 的状态,并删除这个 stash 1 git stash pop 删除所有的 stash 1 git stash clear 从 stash 中拿出某个文件的修改 1 git checkout \u0026lt;stash@{n}\u0026gt; -- \u0026lt;file-path\u0026gt; 展示所有 tracked 的文件 1 git ls-files -t 展示所有 untracked 的文件 1 git ls-files --others 展示所有忽略的文件 1 git ls-files --others -i --exclude-standard 强制删除 untracked 的文件 可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,注意两点:\nclean 后,删除的文件无法找回 不会影响 tracked 的文件的改动,只会删除 untracked 的文件 1 git clean \u0026lt;file-name\u0026gt; -f 强制删除 untracked 的目录 可以用来删除新建的目录,注意:这个命令也可以用来删除 untracked 的文件。详情见上一条\n1 git clean \u0026lt;directory-name\u0026gt; -df 展示简化的 commit 历史 1 git log --pretty=oneline --graph --decorate --all 把某一个分支导出成一个文件 1 git bundle create \u0026lt;file\u0026gt; \u0026lt;branch-name\u0026gt; 从包中导入分支 新建一个分支,分支内容就是上面 git bundle create 命令导出的内容\n1 git clone repo.bundle \u0026lt;repo-dir\u0026gt; -b \u0026lt;branch-name\u0026gt; 执行 rebase 之前自动 stash 1 git rebase --autostash 从远程仓库根据 ID,拉下某一状态,到本地分支 1 git fetch origin pull/\u0026lt;id\u0026gt;/head:\u0026lt;branch-name\u0026gt; 详细展示一行中的修改 1 git diff --word-diff 清除 gitignore 文件中记录的文件 1 git clean -X -f 展示所有 alias 和 configs 注意: config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config\n1 2 git config --local --list (当前目录) git config --global --list (全局) 展示忽略的文件 1 git status --ignored commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit 1 git log Branch1 ^Branch2 在 commit log 中显示 GPG 签名 1 git log --show-signature 删除全局设置 1 git config --global --unset \u0026lt;entry-name\u0026gt; 新建并切换到新分支上,同时这个分支没有任何 commit 相当于保存修改,但是重写 commit 历史\n1 git checkout --orphan \u0026lt;branch-name\u0026gt; 展示任意分支某一文件的内容 1 git show \u0026lt;branch-name\u0026gt;:\u0026lt;file-name\u0026gt; clone 下来指定的单一分支 1 git clone -b \u0026lt;branch-name\u0026gt; --single-branch https://github.com/user/repo.git clone 最新一次提交 只会 clone 最近一次提交,将减少 clone 时间\n1 git clone --depth=1 https://github.com/user/repo.git 忽略某个文件的改动 关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动\n1 git update-index --assume-unchanged path/to/file 恢复 track 指定文件的改动\n1 git update-index --no-assume-unchanged path/to/file 忽略文件的权限变化 不再将文件的权限变化视作改动\n1 git config core.fileMode false 以最后提交的顺序列出所有 Git 分支 最新的放在最上面\n1 git for-each-ref --sort=-committerdate --format=\u0026#39;%(refname:short)\u0026#39; refs/heads/ 在 commit log 中查找相关内容 通过 grep 查找,given-text:所需要查找的字段\n1 git log --all --grep=\u0026#39;\u0026lt;given-text\u0026gt;\u0026#39; 把暂存区的指定 file 放到工作区中 不添加参数,默认是 -mixed\n1 git reset \u0026lt;file-name\u0026gt; 强制推送 1 git push -f \u0026lt;remote-name\u0026gt; \u0026lt;branch-name\u0026gt; ","date":"2023-03-17T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/cover_hub0dc5de02b67b4945e49bf20f42f29b6_29697_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/","title":"【Git版本控制】Git命令详解"},{"content":"今日任务 KMP算法详解 28.实现 strStr() 459.重复的子字符串 字符串总结 双指针回顾 1.KMP算法详解 由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。\n(1)什么是KMP算法 说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。\n因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。\n(2)KMP的作用 KMP主要体现在字符串匹配上。\nKMP算法的主要思想是当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。\n因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。\n(3)什么是前缀表 前缀表有什么作用呢?\n前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。\n其中我们会了解到next数组,next数组其实就是一个前缀表(prefix table)。\n为了更加清楚地了解前缀表的来历,我们来举一个例子:\n在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。\n如下面动画所示(来源:代码随想录):\n我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。\n那么前缀表时如何记录的呢?\n首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。\n所以前缀表的定义是:记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀。\n(4)什么是最长公共前后缀 前文中字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。\n后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。\n那么我们回到最长公共前后缀,更加准确的理解应该是“最长相等前后缀”,因为前缀表的要求就是相同前后缀。\n而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。\n所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。\n(5)如何计算前缀表 我们先来看几个例子:\n解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.\n注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。\n解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.\n解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.\n\u0026hellip;\n以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.\n最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:\n可以看出模式串与前缀表对应位置的数字表示的就是:下标i之前(包括i)的字符串中,有多大长度的相同前后缀.\n我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:\n当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。\n之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。\n所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。\n(5)前缀表与next数组 很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?\n前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。\n(6)使用next数组匹配 以下我们以前缀表统一减一之后的next数组来做演示。\n注意此时的前缀表已经实现同一减一了,匹配动画如下:\n(7)时间复杂度分析 其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)\n而暴力解法的时间复杂度明显是O(n * m),所以可知KMP在字符串匹配中极大地提高了搜索的效率。\n2.Leetcode28.实现 strStr() 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string\n(1)题目 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。\n示例 1:\n1 2 3 4 输入:haystack = \u0026#34;sadbutsad\u0026#34;, needle = \u0026#34;sad\u0026#34; 输出:0 解释:\u0026#34;sad\u0026#34; 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。 示例 2:\n1 2 3 输入:haystack = \u0026#34;leetcode\u0026#34;, needle = \u0026#34;leeto\u0026#34; 输出:-1 解释:\u0026#34;leeto\u0026#34; 没有在 \u0026#34;leetcode\u0026#34; 中出现,所以返回 -1 。 提示:\n1 \u0026lt;= haystack.length, needle.length \u0026lt;= 104 haystack 和 needle 仅由小写英文字符组成 (2)思路 前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。\n在本题目中,haystack(文本串),needle(模式串)。\n解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。\n\u0026lt;1\u0026gt;构造next数组 我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:\n1 void getNext(int* next, const string\u0026amp; s) **构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:\n1.初始化 2.处理前后缀不相同的情况 3.处理前后缀相同的情况 下面我们来详细讲解:\n1.初始化\n定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。\n然后对next数组进行初始化赋值:\n1 2 int j = -1; next[0] = j; 这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)\nnext[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)\n所以初始化为next[0] = j;\n2.处理前后缀不相同的情况\n因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。\n所以遍历模式串s的循环下标i要从1开始,代码如下:\n1 for(int i = 1; i \u0026lt; s.size(); i++){} 如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。\n这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。\ns[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。\n所以,处理前后缀不相同的情况的代码如下所示:\n1 2 3 while(j \u0026gt;= 0 \u0026amp;\u0026amp; s[i] != s[j + 1]){ //前后缀不相同的情况 j = next[j];\t// 向前回退 } 注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。\n3.处理前后缀相同的情况\n如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:\n1 2 3 4 if(s[i] == s[j + 1]){ // 找到相同的前后缀 j++; } next[i] = j; 最后整体构建next数组的函数代码如下所示:\n1 2 3 4 5 6 7 8 9 10 11 12 13 void getNext(int* next, const string\u0026amp; s){ int j = -1; next[0] = j; for(int i = 1; i \u0026lt; s.size(); i++){\t// 注意i从1开始 while(j \u0026gt;= 0 \u0026amp;\u0026amp; s[i] != s[j + 1]){\t// 前后缀不相同的时候 j = next[j];\t// 向前回退 } if(s[i] == s[j + 1]){ // 找到相同的前后缀 j++; } next[i] = j;\t// 将j(前缀的长度)赋值给next[i] } } 代码构造next数组的逻辑流程动画如下(来源:代码随想录):\n\u0026lt;2\u0026gt;使用next数组进行匹配 目标:在文本串中找是否出现过模式串t。\n首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。\n此时j初始值依然为-1,因为next数组中记录的起始位置为-1.\ni从0开始,遍历文本串,代码如下:\n1 for(int i = 0; i \u0026lt; s.size(); i++) 接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。\n如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:\n1 2 3 while(j \u0026gt;= 0 \u0026amp;\u0026amp; s[i] != t[j + 1]){ j = next[j]; } 如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:\n1 2 3 if(s[i] == t[j + 1]){ j++;\t// i的增加在for循环中定义 } 那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。\n模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:\n1 2 3 if(j == (t.size() - 1)){ return (i - t.size() + 1); } 因此使用next数组,用模式串匹配文本串的整体代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 int j = -1;\t// 因为next数组里记录的起始位置为-1 for(int i = 0; i \u0026lt; s.size(); i++){\t// 注意i从0开始 while(j \u0026gt;= 0 \u0026amp;\u0026amp; s[i] != t[j + 1]){\t// 不匹配 j = next[j]; // j寻找之前匹配的位置 } if(s[i] == t[j + 1]){\t// 匹配,j和i同时向后移动 j++;\t// i的增加在for循环中 } if(j == (t.size() - 1)){\t// 文本串s里出现了模式串t return (i - t.size() + 1); } } (3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // 前缀表统一减一 class Solution { public: void getNext(int* next, const string\u0026amp; s) { int j = -1; next[0] = j; for(int i = 1; i \u0026lt; s.size(); i++) { // 注意i从1开始 while (j \u0026gt;= 0 \u0026amp;\u0026amp; s[i] != s[j + 1]) { // 前后缀不相同了 j = next[j]; // 向前回退 } if (s[i] == s[j + 1]) { // 找到相同的前后缀 j++; } next[i] = j; // 将j(前缀的长度)赋给next[i] } } int strStr(string haystack, string needle) { if (needle.size() == 0) { return 0; } int next[needle.size()]; getNext(next, needle); int j = -1; // // 因为next数组里记录的起始位置为-1 for (int i = 0; i \u0026lt; haystack.size(); i++) { // 注意i就从0开始 while(j \u0026gt;= 0 \u0026amp;\u0026amp; haystack[i] != needle[j + 1]) { // 不匹配 j = next[j]; // j 寻找之前匹配的位置 } if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动 j++; // i的增加在for循环里 } if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串t return (i - needle.size() + 1); } } return -1; } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // 前缀表(不减一) class Solution { public: void getNext(int* next, const string\u0026amp; s) { int j = 0; next[0] = 0; for(int i = 1; i \u0026lt; s.size(); i++) { while (j \u0026gt; 0 \u0026amp;\u0026amp; s[i] != s[j]) { j = next[j - 1]; } if (s[i] == s[j]) { j++; } next[i] = j; } } int strStr(string haystack, string needle) { if (needle.size() == 0) { return 0; } int next[needle.size()]; getNext(next, needle); int j = 0; for (int i = 0; i \u0026lt; haystack.size(); i++) { while(j \u0026gt; 0 \u0026amp;\u0026amp; haystack[i] != needle[j]) { j = next[j - 1]; } if (haystack[i] == needle[j]) { j++; } if (j == needle.size() ) { return (i - needle.size() + 1); } } return -1; } }; 3.Leetcode459.重复的子字符串 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/repeated-substring-pattern\n(1)题目 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。\n示例 1:\n1 2 3 输入: s = \u0026#34;abab\u0026#34; 输出: true 解释: 可由子串 \u0026#34;ab\u0026#34; 重复两次构成。 示例 2:\n1 2 输入: s = \u0026#34;aba\u0026#34; 输出: false 示例 3:\n1 2 3 输入: s = \u0026#34;abcabcabcabc\u0026#34; 输出: true 解释: 可由子串 \u0026#34;abc\u0026#34; 重复四次构成。 (或子串 \u0026#34;abcabc\u0026#34; 重复两次构成。) 提示:\n1 \u0026lt;= s.length \u0026lt;= 104 s 由小写英文字母组成 (2)思路 对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。\n首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。\n这里我们主要对移动匹配和KMP两种方法进行讲解。\n\u0026lt;1\u0026gt;移动匹配 首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:\n那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。\n所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。\n这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行掐头去尾(刨除s+s的首字符和尾字符),代码如下:\n1 2 3 4 5 6 7 8 9 10 class Solution{ public: bool repeatedSubstringPatterns(string s){ string t = s + s; t.erase(t.begin()); t.erase(t.end() - 1);\t// 掐头去尾 if(t.find(s) != std::string::npos) return true; return false; } }; 虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。\n\u0026lt;2\u0026gt;KMP 想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.\n代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public: void getNext(int* next, const string\u0026amp; s){ next[0] = 0; int j = 0; for(int i = 1;i \u0026lt; s.size(); i++){ while(j \u0026gt; 0 \u0026amp;\u0026amp; s[i] != s[j]){ j = next[j - 1]; } if(s[i] == s[j]){ j++; } next[i] = j; } } bool repeatedSubstringPattern(string s) { if(s.size() == 0){ return false; } int next[s.size()]; getNext(next, s); int len = s.size(); if(next[len - 1] != 0 \u0026amp;\u0026amp; len % (len - (next[len - 1])) == 0){ return true; } return false; } }; 4.字符串总结 对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。\n","date":"2023-03-13T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover_hu0ba98275d6445c79f820f07c37ff307c_142192_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/","title":"【数据结构与算法】字符串2:KMP \u0026 实现 strStr() \u0026 重复的子字符串"},{"content":"今日任务 344.反转字符串 541.反转字符串II 剑指Offer 05.替换空格 151.反转字符串里的单词 剑指Offer58-II.左旋转字符串 1.Leetcode344.反转字符串 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/reverse-string\n(1)题目 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。\n不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。\n示例 1:\n1 2 输入:s = [\u0026#34;h\u0026#34;,\u0026#34;e\u0026#34;,\u0026#34;l\u0026#34;,\u0026#34;l\u0026#34;,\u0026#34;o\u0026#34;] 输出:[\u0026#34;o\u0026#34;,\u0026#34;l\u0026#34;,\u0026#34;l\u0026#34;,\u0026#34;e\u0026#34;,\u0026#34;h\u0026#34;] 示例 2:\n1 2 输入:s = [\u0026#34;H\u0026#34;,\u0026#34;a\u0026#34;,\u0026#34;n\u0026#34;,\u0026#34;n\u0026#34;,\u0026#34;a\u0026#34;,\u0026#34;h\u0026#34;] 输出:[\u0026#34;h\u0026#34;,\u0026#34;a\u0026#34;,\u0026#34;n\u0026#34;,\u0026#34;n\u0026#34;,\u0026#34;a\u0026#34;,\u0026#34;H\u0026#34;] 提示:\n1 \u0026lt;= s.length \u0026lt;= 105 s[i] 都是 ASCII 码表中的可打印字符 (2)思路 看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。\n那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。\n对应的部分C++代码:\n1 2 3 4 5 void reverseString(vector\u0026lt;char\u0026gt;\u0026amp; s){ for(int i = 0, j = s.size() - 1; i \u0026lt; s.size() / 2; i++,j--){ swap(s[i], s[j]); } } (3)代码演示 1 2 3 4 5 6 7 8 class Solution { public: void reverseString(vector\u0026lt;char\u0026gt;\u0026amp; s) { for (int i = 0, j = s.size() - 1; i \u0026lt; s.size()/2; i++, j--) { swap(s[i],s[j]); } } }; 2.Leetcode541.反转字符串II 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/reverse-string-ii\n(1)题目 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。\n如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。 示例 1:\n1 2 输入:s = \u0026#34;abcdefg\u0026#34;, k = 2 输出:\u0026#34;bacdfeg\u0026#34; 示例 2:\n1 2 输入:s = \u0026#34;abcd\u0026#34;, k = 2 输出:\u0026#34;bacd\u0026#34; 提示:\n1 \u0026lt;= s.length \u0026lt;= 104 s 仅由小写英文组成 1 \u0026lt;= k \u0026lt;= 104 (2)思路 我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。\n该题主要需要解决两个问题:\n每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符 对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符 具体详细的解题步骤请看下图及代码:\n(3)代码演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public: // 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 void reverse(string\u0026amp; s, int start, int end) { for (int i = start, j = end; i \u0026lt; j; i++, j--) { swap(s[i], s[j]); } } string reverseStr(string s, int k) { for (int i = 0; i \u0026lt; s.size(); i += (2 * k)) { // 1. 每隔 2k 个字符的前 k 个字符进行反转 // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 if (i + k \u0026lt;= s.size()) { reverse(s, i, i + k - 1); continue; } // 3. 剩余字符少于 k 个,则将剩余字符全部反转。 reverse(s, i, s.size() - 1); } return s; } }; reverse()\nreverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值 3.剑指Offer 05.替换空格 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof\n(1)题目 请实现一个函数,把字符串 s 中的每个空格替换成\u0026quot;%20\u0026quot;。\n示例 1:\n1 2 输入:s = \u0026#34;We are happy.\u0026#34; 输出:\u0026#34;We%20are%20happy.\u0026#34; 限制:\n0 \u0026lt;= s 的长度 \u0026lt;= 10000 (2)思路 对这道题的求解,主要分三个步骤:\n首先扩充数组到每个空格替换成\u0026quot;%20\u0026quot;之后的大小 然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录) i指向新长度的末尾,j指向旧长度的末尾 而这里也有一个小技巧:遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。\n这样做的好处:\n不用申请新数组 从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。 (3)代码演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public: string replaceSpace(string s) { int count = 0; // 统计空格的个数 int sOldSize = s.size(); for (int i = 0; i \u0026lt; s.size(); i++) { if (s[i] == \u0026#39; \u0026#39;) { count++; } } // 扩充字符串s的大小,也就是每个空格替换成\u0026#34;%20\u0026#34;之后的大小 s.resize(s.size() + count * 2); // 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 int sNewSize = s.size(); // 从后先前将空格替换为\u0026#34;%20\u0026#34; for (int i = sNewSize - 1, j = sOldSize - 1; j \u0026lt; i; i--, j--) { if (s[j] != \u0026#39; \u0026#39;) { s[i] = s[j]; } else { s[i] = \u0026#39;0\u0026#39;; s[i - 1] = \u0026#39;2\u0026#39;; s[i - 2] = \u0026#39;%\u0026#39;; i -= 2; } } return s; } }; resize()\n既分配了空间,也创建了对象。 这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。 4.Leetcode151.反转字符串里的单词 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/reverse-words-in-a-string\n(1)题目 给你一个字符串 s ,请你反转字符串中 单词 的顺序。\n单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。\n返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。\n注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。\n示例 1:\n1 2 输入:s = \u0026#34;the sky is blue\u0026#34; 输出:\u0026#34;blue is sky the\u0026#34; 示例 2:\n1 2 3 输入:s = \u0026#34; hello world \u0026#34; 输出:\u0026#34;world hello\u0026#34; 解释:反转后的字符串中不能存在前导空格和尾随空格。 示例 3:\n1 2 3 输入:s = \u0026#34;a good example\u0026#34; 输出:\u0026#34;example good a\u0026#34; 解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。 提示:\n1 \u0026lt;= s.length \u0026lt;= 104 s 包含英文大小写字母、数字和空格 \u0026rsquo; ' s 中 至少存在一个 单词 进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。\n(2)思路 对于这样一道题,我们不使用辅助空间,空间复杂度要求为O(1)\n所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决\n首先移除掉多余的空格 将整个字符串反转 再将每个单词反转 演示如下:\n前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看移除多余空格:我们的做法是通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格。\n1 2 3 4 5 6 7 8 9 10 11 12 void removeExtraSpaces(string\u0026amp; s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。 int slow = 0; for (int i = 0; i \u0026lt; s.size(); ++i) { // if (s[i] != \u0026#39; \u0026#39;) { //遇到非空格就处理,即删除所有空格。 if (slow != 0) s[slow++] = \u0026#39; \u0026#39;; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 while (i \u0026lt; s.size() \u0026amp;\u0026amp; s[i] != \u0026#39; \u0026#39;) { //补上该单词,遇到空格说明单词结束。 s[slow++] = s[i++]; } } } s.resize(slow); //slow的大小即为去除多余空格后的大小。 } 此外就是字符串反转的问题,其代码实现逻辑如下:\n1 2 3 4 5 6 // 反转字符串s中左闭右闭的区间[start, end] void reverse(string\u0026amp; s, int start, int end) { for (int i = start, j = end; i \u0026lt; j; i++, j--) { swap(s[i], s[j]); } } (3)代码演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public: void reverse(string\u0026amp; s, int start, int end){ //翻转,区间写法:左闭右闭 [] for (int i = start, j = end; i \u0026lt; j; i++, j--) { swap(s[i], s[j]); } } void removeExtraSpaces(string\u0026amp; s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。 int slow = 0; //整体思想参考https://programmercarl.com/0027.移除元素.html for (int i = 0; i \u0026lt; s.size(); ++i) { // if (s[i] != \u0026#39; \u0026#39;) { //遇到非空格就处理,即删除所有空格。 if (slow != 0) s[slow++] = \u0026#39; \u0026#39;; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 while (i \u0026lt; s.size() \u0026amp;\u0026amp; s[i] != \u0026#39; \u0026#39;) { //补上该单词,遇到空格说明单词结束。 s[slow++] = s[i++]; } } } s.resize(slow); //slow的大小即为去除多余空格后的大小。 } string reverseWords(string s) { removeExtraSpaces(s); //去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 reverse(s, 0, s.size() - 1);// 反转字符串 int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。 for (int i = 0; i \u0026lt;= s.size(); ++i) { if (i == s.size() || s[i] == \u0026#39; \u0026#39;) { //到达空格或者串尾,说明一个单词结束。进行翻转。 reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。 start = i + 1; //更新下一个单词的开始下标start } } return s; } }; 5.剑指Offer58-II.左旋转字符串 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof\n(1)题目 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串\u0026quot;abcdefg\u0026quot;和数字2,该函数将返回左旋转两位得到的结果\u0026quot;cdefgab\u0026quot;。\n示例 1:\n1 2 输入: s = \u0026#34;abcdefg\u0026#34;, k = 2 输出: \u0026#34;cdefgab\u0026#34; 示例 2:\n1 2 输入: s = \u0026#34;lrloseumgh\u0026#34;, k = 6 输出: \u0026#34;umghlrlose\u0026#34; 限制:\n1 \u0026lt;= k \u0026lt; s.length \u0026lt;= 10000 (2)思路 在本题目中,carl老师继续升级难度:要求不能申请额外空间,只能在本串上操作\n但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:\n反转区间为前n的子串 反转区间为n到末尾的子串 反转整个字符串 这样一来,整体的代码逻辑就特别简单啦!\n(3)代码演示 1 2 3 4 5 6 7 8 9 class Solution { public: string reverseLeftWords(string s, int n) { reverse(s.begin(), s.begin() + n); reverse(s.begin() + n, s.end()); reverse(s.begin(), s.end()); return s; } }; 没想到最后一个代码的实现这么简单哈哈哈,在经历Leetcode151.反转字符串里的单词这道题的洗礼后是不是有种小巫见大巫的想法。\n","date":"2023-02-22T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover_hubd45134fe7e482c9d30a491cd239645b_134507_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/","title":"【数据结构与算法】字符串1:反转字符串I \u0026 反转字符串II \u0026反转字符串里的单词 \u0026 剑指offer(替换空格、左旋转字符串)"},{"content":"今日任务 454.四数相加II 383.赎金信 15.三数之和 18.四数之和 1.Leetcode454.四数相加II 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/4sum-ii\n(1)题目 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:\n0 \u0026lt;= i, j, k, l \u0026lt; n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 示例 1:\n1 2 3 4 5 6 7 输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) -\u0026gt; nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -\u0026gt; nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0 示例 2:\n1 2 输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 输出:1 提示:\nn == nums1.length n == nums2.length n == nums3.length n == nums4.length 1 \u0026lt;= n \u0026lt;= 200 -228 \u0026lt;= nums1[i], nums2[i], nums3[i], nums4[i] \u0026lt;= 228 (2)思路 分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。\n解题步骤:\n首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。 定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。 在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。 最后再返回统计值count就可以了。 (3)代码演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public: int fourSumCount(vector\u0026lt;int\u0026gt;\u0026amp; nums1, vector\u0026lt;int\u0026gt;\u0026amp; nums2, vector\u0026lt;int\u0026gt;\u0026amp; nums3, vector\u0026lt;int\u0026gt;\u0026amp; nums4) { unordered_map\u0026lt;int, int\u0026gt; umap; // key:a+b的数值,value:a+b数值出现的次数 for(int a : nums1){ for(int b : nums2){ umap[a + b]++; // 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 } } int count = 0; // 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 // 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 for(int c : nums3){ for(int d : nums4){ if(umap.find(0 - (c + d)) != umap.end()){ count += umap[0 - (c + d)];// 此处 umap[key]可以直接访问满足key的value值 } } } return count; } }; 2.Leetcode383.赎金信 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/ransom-note\n(1)题目 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。\n如果可以,返回 true ;否则返回 false 。\nmagazine 中的每个字符只能在 ransomNote 中使用一次。\n示例 1:\n1 2 输入:ransomNote = \u0026#34;a\u0026#34;, magazine = \u0026#34;b\u0026#34; 输出:false 示例 2:\n1 2 输入:ransomNote = \u0026#34;aa\u0026#34;, magazine = \u0026#34;ab\u0026#34; 输出:false 示例 3:\n1 2 输入:ransomNote = \u0026#34;aa\u0026#34;, magazine = \u0026#34;aab\u0026#34; 输出:true 提示:\n1 \u0026lt;= ransomNote.length, magazine.length \u0026lt;= 105 ransomNote 和 magazine 由小写英文字母组成 (2)思路 首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。\n对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的,所以数组和map果断选择map。\n暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。\n使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一\n(3)暴力解法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 时间复杂度: O(n^2) // 空间复杂度:O(1) class Solution { public: bool canConstruct(string ransomNote, string magazine) { for (int i = 0; i \u0026lt; magazine.length(); i++) { for (int j = 0; j \u0026lt; ransomNote.length(); j++) { // 在ransomNote中找到和magazine相同的字符 if (magazine[i] == ransomNote[j]) { ransomNote.erase(ransomNote.begin() + j); // ransomNote删除这个字符 break; } } } // 如果ransomNote为空,则说明magazine的字符可以组成ransomNote if (ransomNote.length() == 0) { return true; } return false; } }; (4)哈希解法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // 时间复杂度: O(n) // 空间复杂度:O(1) class Solution { public: bool canConstruct(string ransomNote, string magazine) { int record[26] = {0}; //add if (ransomNote.size() \u0026gt; magazine.size()) { return false; } for (int i = 0; i \u0026lt; magazine.length(); i++) { // 通过recode数据记录 magazine里各个字符出现次数 record[magazine[i]-\u0026#39;a\u0026#39;] ++; } for (int j = 0; j \u0026lt; ransomNote.length(); j++) { // 遍历ransomNote,在record里对应的字符个数做--操作 record[ransomNote[j]-\u0026#39;a\u0026#39;]--; // 如果小于零说明ransomNote里出现的字符,magazine没有 if(record[ransomNote[j]-\u0026#39;a\u0026#39;] \u0026lt; 0) { return false; } } return true; } }; 3.Leetcode15.三数之和 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/3sum\n(1)题目 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。\n注意:答案中不可以包含重复的三元组。\n示例 1:\n1 2 3 4 5 6 7 8 输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。 示例 2:\n1 2 3 输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。 示例 3:\n1 2 3 输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。 提示:\n3 \u0026lt;= nums.length \u0026lt;= 3000 -105 \u0026lt;= nums[i] \u0026lt;= 105 (2)思路 这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了答案中不可包含重复的三元组。所以解题思路不能一概而论,同样可以使用哈希解法,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。\n那么另外一种解题思路就是使用双指针法。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:\n我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:\nnums[i] + nums[left] + nums[right] \u0026gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动 nums[i] + nums[left] + nums[right] = 0 :返回结果 nums[i] + nums[left] + nums[right] \u0026lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动 此外,我们还需要解决去重的问题:\n\u0026lt;1\u0026gt;对a去重:\n按照一贯的理解我们可能是下面这种做法:\n1 2 3 if (i \u0026gt; 0 \u0026amp;\u0026amp; nums[i] == nums[i + 1]) { //三元组元素a去重 continue; } 但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:返回不能有重复的三元组,但是三元组内的元素是可以重复的,如果按照上面的写法,那么我们很可能漏掉一组解。\n所以应该是下面这段代码这样:\n1 2 3 if (i \u0026gt; 0 \u0026amp;\u0026amp; nums[i] == nums[i - 1]) { //三元组元素a去重 continue; } \u0026lt;2\u0026gt;b与c的去重:\n当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。\n1 2 3 // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 while (right \u0026gt; left \u0026amp;\u0026amp; nums[right] == nums[right - 1]) right--; while (right \u0026gt; left \u0026amp;\u0026amp; nums[left] == nums[left + 1]) left++; 1 2 3 // 找到答案时,双指针同时收缩 right--; left++; (3)哈希解法* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public: vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; threeSum(vector\u0026lt;int\u0026gt;\u0026amp; nums) { vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; result; sort(nums.begin(), nums.end()); // 找出a + b + c = 0 // a = nums[i], b = nums[j], c = -(a + b) for (int i = 0; i \u0026lt; nums.size(); i++) { // 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 if (nums[i] \u0026gt; 0) { break; } if (i \u0026gt; 0 \u0026amp;\u0026amp; nums[i] == nums[i - 1]) { //三元组元素a去重 continue; } unordered_set\u0026lt;int\u0026gt; set; for (int j = i + 1; j \u0026lt; nums.size(); j++) { if (j \u0026gt; i + 2 \u0026amp;\u0026amp; nums[j] == nums[j-1] \u0026amp;\u0026amp; nums[j-1] == nums[j-2]) { // 三元组元素b去重 continue; } int c = 0 - (nums[i] + nums[j]); if (set.find(c) != set.end()) { result.push_back({nums[i], nums[j], c}); set.erase(c);// 三元组元素c去重 } else { set.insert(nums[j]); } } } return result; } }; (4)双指针法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Solution { public: vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; threeSum(vector\u0026lt;int\u0026gt;\u0026amp; nums) { vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; result; sort(nums.begin(), nums.end()); // 找出a + b + c = 0 // a = nums[i], b = nums[left], c = nums[right] for (int i = 0; i \u0026lt; nums.size(); i++) { // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 if (nums[i] \u0026gt; 0) { return result; } // 错误去重a方法,将会漏掉-1,-1,2 这种情况 /* if (nums[i] == nums[i + 1]) { continue; } */ // 正确去重a方法 if (i \u0026gt; 0 \u0026amp;\u0026amp; nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = nums.size() - 1; while (right \u0026gt; left) { // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right\u0026lt;=left 了,从而漏掉了 0,0,0 这种三元组 /* while (right \u0026gt; left \u0026amp;\u0026amp; nums[right] == nums[right - 1]) right--; while (right \u0026gt; left \u0026amp;\u0026amp; nums[left] == nums[left + 1]) left++; */ if (nums[i] + nums[left] + nums[right] \u0026gt; 0) right--; else if (nums[i] + nums[left] + nums[right] \u0026lt; 0) left++; else { result.push_back(vector\u0026lt;int\u0026gt;{nums[i], nums[left], nums[right]}); // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 while (right \u0026gt; left \u0026amp;\u0026amp; nums[right] == nums[right - 1]) right--; while (right \u0026gt; left \u0026amp;\u0026amp; nums[left] == nums[left + 1]) left++; // 找到答案时,双指针同时收缩 right--; left++; } } } return result; } }; 4.Leetcode18.四数之和 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/4sum\n(1)题目 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):\n0 \u0026lt;= a, b, c, d \u0026lt; n\na、b、c 和 d 互不相同\nnums[a] + nums[b] + nums[c] + nums[d] == target\n你可以按 任意顺序 返回答案 。\n示例 1:\n1 2 输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]] 示例 2:\n1 2 输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]] 提示:\n1 \u0026lt;= nums.length \u0026lt;= 200 -109 \u0026lt;= nums[i] \u0026lt;= 109 -109 \u0026lt;= target \u0026lt;= 109 (2)思路 这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。\n但是有些许细节需要我们认真对待:\n在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。 在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是nums[k] + nums[i] + nums[left] + nums[right] == target的所有可解集合,所以我们的解决方法是两层for循环nums[k] + nums[i]为确定值,双指针法依然是left和right作为下标。 三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。 (3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution { public: vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; fourSum(vector\u0026lt;int\u0026gt;\u0026amp; nums, int target) { vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; result; sort(nums.begin(), nums.end()); for (int k = 0; k \u0026lt; nums.size(); k++) { // 剪枝处理 if (nums[k] \u0026gt; target \u0026amp;\u0026amp; nums[k] \u0026gt;= 0) { break; // 这里使用break,统一通过最后的return返回 } // 对nums[k]去重 if (k \u0026gt; 0 \u0026amp;\u0026amp; nums[k] == nums[k - 1]) { continue; } for (int i = k + 1; i \u0026lt; nums.size(); i++) { // 2级剪枝处理 if (nums[k] + nums[i] \u0026gt; target \u0026amp;\u0026amp; nums[k] + nums[i] \u0026gt;= 0) { break; } // 对nums[i]去重 if (i \u0026gt; k + 1 \u0026amp;\u0026amp; nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = nums.size() - 1; while (right \u0026gt; left) { // nums[k] + nums[i] + nums[left] + nums[right] \u0026gt; target 会溢出 if ((long) nums[k] + nums[i] + nums[left] + nums[right] \u0026gt; target) { right--; // nums[k] + nums[i] + nums[left] + nums[right] \u0026lt; target 会溢出 } else if ((long) nums[k] + nums[i] + nums[left] + nums[right] \u0026lt; target) { left++; } else { result.push_back(vector\u0026lt;int\u0026gt;{nums[k], nums[i], nums[left], nums[right]}); // 对nums[left]和nums[right]去重 while (right \u0026gt; left \u0026amp;\u0026amp; nums[right] == nums[right - 1]) right--; while (right \u0026gt; left \u0026amp;\u0026amp; nums[left] == nums[left + 1]) left++; // 找到答案时,双指针同时收缩 right--; left++; } } } } return result; } }; ","date":"2023-02-21T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover_hu0ba98275d6445c79f820f07c37ff307c_127855_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/","title":"【数据结构与算法】哈希表2:四数相加II \u0026 赎金信 \u0026 三数之和 \u0026 四数之和"},{"content":"今日任务 哈希表理论基础\n242.有效的字母异位词\n349.两个数组的交集\n202.快乐数\n1.两数之和\n1.哈希表理论基础 (1)哈希表 哈希表(Hash table,国内也有一些书籍翻译为散列表):是根据关键码的值而直接访问的数据结构。\n最常见的哈希表例子就是数组。\n哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:\n那么哈希表一般适用于哪些场景呢?一般哈希表都是用来快速判断一个元素是否出现在集合里。\n例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。\n我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。\n这里将商品列表映射到哈希表上就涉及到哈希函数(Hash function)。\n(2)哈希函数 哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。\n哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。\n此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?\n为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。\n此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。\n这时候就需要引入哈希碰撞了。\n(3)哈希碰撞 如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为哈希碰撞。\n对于哈希碰撞一般有两种解决方法:链地址法(拉链法)和线性探测法\n(4)链地址法(拉链法) 这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。\n由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了\n(5)线性探测法 使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。\n例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。\n此外对于哈希碰撞的常用解决方法还有开放定址法、再哈希法、建立公共溢出区等等\u0026hellip;\n(6)常见的三种哈希结构 当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:\n数组 set(集合) map(映射) 数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):\nset(集合)\n在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:\n集合 底层实现 是否有序 数值是否可以重复 能否更改数值 查询效率 增删效率 std::set 红黑树 有序 否 否 O(log n) O(log n) std::multiset 红黑树 有序 是 否 O(logn) O(logn) std::unordered_set 哈希表 无序 否 否 O(1) O(1) map(映射)\n映射 底层实现 是否有序 数值是否可以重复 能否更改数值 查询效率 增删效率 std::map 红黑树 key有序 key不可重复 key不可修改 O(logn) O(logn) std::multimap 红黑树 key有序 key可重复 key不可修改 O(log n) O(log n) std::unordered_map 哈希表 key无序 key不可重复 key不可修改 O(1) O(1) (7)总结 当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。\n但是哈希法的缺点也显而易见的:牺牲空间去换取时间。\n2.Leetcode242.有效的字母异位词 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/valid-anagram\n(1)题目 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。\n注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。\n示例 1:\n1 2 输入: s = \u0026#34;anagram\u0026#34;, t = \u0026#34;nagaram\u0026#34; 输出: true 示例 2:\n1 2 输入: s = \u0026#34;rat\u0026#34;, t = \u0026#34;car\u0026#34; 输出: false 提示:\n1 \u0026lt;= s.length, t.length \u0026lt;= 5 * 104 s 和 t 仅包含小写字母 进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?\n(2)思路 前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。\n由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.\n例如,我们对字符串s = \u0026ldquo;aee\u0026rdquo;, t = \u0026lsquo;\u0026ldquo;eae\u0026rdquo;,我们观察动画:\n我们定义一个record的数组来记录字符串s里所有字符出现的次数。\n需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。\n在遍历字符串s的时候,只需要将s[i] = \u0026lsquo;a\u0026rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.\n最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。\n时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public: bool isAnagram(string s, string t) { int record[26] = {0}; for (int i = 0; i \u0026lt; s.size(); i++) { // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 record[s[i] - \u0026#39;a\u0026#39;]++; } for (int i = 0; i \u0026lt; t.size(); i++) { record[t[i] - \u0026#39;a\u0026#39;]--; } for (int i = 0; i \u0026lt; 26; i++) { if (record[i] != 0) { // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 return false; } } // record数组所有元素都为零0,说明字符串s和t是字母异位词 return true; } }; 3.Leetcode349. 两个数组的交集 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/intersection-of-two-arrays\n(1)题目 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。\n示例 1:\n1 2 输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2] 示例 2:\n1 2 3 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的 提示:\n1 \u0026lt;= nums1.length, nums2.length \u0026lt;= 1000 0 \u0026lt;= nums1[i], nums2[i] \u0026lt;= 1000 (2)思路 在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:\n题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。\n之所以这里不使用数组,是因为题目限制了数组的大小,并且如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。\n所以结合std::unordered_set的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public: vector\u0026lt;int\u0026gt; intersection(vector\u0026lt;int\u0026gt;\u0026amp; nums1, vector\u0026lt;int\u0026gt;\u0026amp; nums2) { unordered_set\u0026lt;int\u0026gt; result_set; // 存放结果,之所以用set是为了给结果集去重 unordered_set\u0026lt;int\u0026gt; nums_set(nums1.begin(), nums1.end());// 定义哈希表存放结果 for (int num : nums2) { // 发现nums2的元素 在nums_set里又出现过 if (nums_set.find(num) != nums_set.end()) { // 在nums1中查找num(nums2) result_set.insert(num);// 如果发现与nums(nums2)的元素,向result_set插入该元素 } } return vector\u0026lt;int\u0026gt;(result_set.begin(), result_set.end()); } }; 当然这道题也可以使用数组的方式进行求解:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public: vector\u0026lt;int\u0026gt; intersection(vector\u0026lt;int\u0026gt;\u0026amp; nums1, vector\u0026lt;int\u0026gt;\u0026amp; nums2) { unordered_set\u0026lt;int\u0026gt; result_set; // 存放结果,之所以用set是为了给结果集去重 int hash[1005] = {0}; // 默认数值为0 for (int num : nums1) { // nums1中出现的字母在hash数组中做记录 hash[num] = 1; } for (int num : nums2) { // nums2中出现话,result记录 if (hash[num] == 1) { result_set.insert(num); } } return vector\u0026lt;int\u0026gt;(result_set.begin(), result_set.end()); } }; 4.Leetcode202.快乐数 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/happy-number\n(1)题目 编写一个算法来判断一个数 n 是不是快乐数。\n**「快乐数」 **定义为:\n对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。\n然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。\n如果这个过程 结果为 1,那么这个数就是快乐数。\n如果 n 是 快乐数 就返回 true ;不是,则返回 false 。\n示例 1:\n1 2 3 4 5 6 7 输入:n = 19 输出:true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1 示例 2:\n1 2 输入:n = 2 输出:false 提示:\n1 \u0026lt;= n \u0026lt;= 231 - 1 (2)思路 根据题目所给出的提示:重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。\n简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?\n那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public: // 取数值各个位上的单数平方之和 int getSum(int n) { int sum = 0; while (n) { sum += (n % 10) * (n % 10); // n每位数的平方和 n /= 10; } return sum; } bool isHappy(int n) { unordered_set\u0026lt;int\u0026gt; set; while(1) { int sum = getSum(n); if (sum == 1) { return true; } // 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false if (set.find(sum) != set.end()) { return false; } else { set.insert(sum); // 记录第一次出现的数 } n = sum; } } }; 5.Leetcode1.两数之和 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/two-sum\n(1)题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。\n你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。\n你可以按任意顺序返回答案。\n示例 1:\n1 2 3 输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 示例 2:\n1 2 输入:nums = [3,2,4], target = 6 输出:[1,2] 示例 3:\n1 2 输入:nums = [3,3], target = 6 输出:[0,1] 提示:\n2 \u0026lt;= nums.length \u0026lt;= 104 -109 \u0026lt;= nums[i] \u0026lt;= 109 -109 \u0026lt;= target \u0026lt;= 109 只会存在一个有效答案 进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?\n(2)思路 根据提示:只存在一个有效答案。所以我们这里可以选择unordered_map\n接下来我们明确两点:\nmap用来做什么 map中key和value分别表示什么 拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合\t因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。\n所以在map中的存储结构为:{key:数据元素, value:数组元素对应的下标}\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public: vector\u0026lt;int\u0026gt; twoSum(vector\u0026lt;int\u0026gt;\u0026amp; nums, int target) { std::unordered_map \u0026lt;int,int\u0026gt; map; for(int i = 0; i \u0026lt; nums.size(); i++) { // 遍历当前元素,并在map中寻找是否有匹配的key auto iter = map.find(target - nums[i]); if(iter != map.end()) { return {iter-\u0026gt;second, i}; } // 如果没找到匹配对,就把访问过的元素和下标加入到map中 map.insert(pair\u0026lt;int, int\u0026gt;(nums[i], i)); } return {}; } }; ","date":"2023-02-20T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover_hu0ba98275d6445c79f820f07c37ff307c_145062_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/","title":"【数据结构与算法】哈希表1:字母异位词 \u0026 两数交集 \u0026 快乐数 \u0026 两数之和"},{"content":"今日任务 24.两两交换链表中的节点\n19.删除链表的倒数第N个节点\n面试题02.07.链表相交\n142.环形链表II\n总结\n1.Leetcode24:两两交换链表中的节点 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/swap-nodes-in-pairs\n(1)题目 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。\n示例 1:\n1 2 输入:head = [1,2,3,4] 输出:[2,1,4,3] 示例 2:\n1 2 输入:head = [] 输出:[] 示例 3:\n1 2 输入:head = [1] 输出:[1] 提示:\n链表中节点的数目在范围 [0, 100] 内 0 \u0026lt;= Node.val \u0026lt;= 100 (2)思路 前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:\n1.直接使用原来的链表进行删除操作。 2.设置一个虚拟头节点再进行删除操作。 相比较第一种,第二种虚拟头节点的形式更加方便。\n初始时,cur指向虚拟头节点,然后依次进行三步:\n步骤1:将原链表的头节点变成节点2 步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点) 步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出) ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表 操作后的链表:\n终止条件:\n当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public: ListNode* swapPairs(ListNode* head) { ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点 dummyHead-\u0026gt;next = head; // 将虚拟头结点指向head,这样方面后面做删除操作 ListNode* cur = dummyHead; while(cur-\u0026gt;next != nullptr \u0026amp;\u0026amp; cur-\u0026gt;next-\u0026gt;next != nullptr) { ListNode* tmp = cur-\u0026gt;next; // 记录临时节点,原本的头节点 ListNode* tmp1 = cur-\u0026gt;next-\u0026gt;next-\u0026gt;next; // 记录临时节点,原本的节点3 cur-\u0026gt;next = cur-\u0026gt;next-\u0026gt;next; // 步骤一 cur-\u0026gt;next-\u0026gt;next = tmp; // 步骤二 cur-\u0026gt;next-\u0026gt;next-\u0026gt;next = tmp1; // 步骤三 cur = cur-\u0026gt;next-\u0026gt;next; // cur移动两位,准备下一轮交换 } return dummyHead-\u0026gt;next; } }; 2.Leetcode19:删除链表的倒数第N个节点 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list\n(1)题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。\n示例 1:\n1 2 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例 2:\n1 2 输入:head = [1], n = 1 输出:[] 示例 3:\n1 2 输入:head = [1,2], n = 1 输出:[1] 提示:\n链表中结点的数目为 sz 1 \u0026lt;= sz \u0026lt;= 30 0 \u0026lt;= Node.val \u0026lt;= 100 1 \u0026lt;= n \u0026lt;= sz 进阶:你能尝试使用一趟扫描实现吗?\n(2)思路 先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-\u0026gt;next = slow-\u0026gt;next-\u0026gt;next即可完成对目标节点的删除。\n同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。\n\u0026lt;1\u0026gt;首先定义fast指针和slow指针,初始值为虚拟头节点:\n\u0026lt;2\u0026gt;fast走n+1步(因为加入了虚拟头节点)\n\u0026lt;3\u0026gt;fast和slow同时移动,直到fast指向链表末\n\u0026lt;4\u0026gt;删除slow指向的下一个节点\n(3)快慢指针法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* dummyHead = new ListNode(0); dummyHead-\u0026gt;next = head; ListNode* slow = dummyHead; ListNode* fast = dummyHead; while(n-- \u0026amp;\u0026amp; fast != NULL) {\t// 让fast指向目标节点 fast = fast-\u0026gt;next; } fast = fast-\u0026gt;next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点 while (fast != NULL) { fast = fast-\u0026gt;next; slow = slow-\u0026gt;next; } slow-\u0026gt;next = slow-\u0026gt;next-\u0026gt;next; // ListNode *tmp = slow-\u0026gt;next; C++释放内存的逻辑 // slow-\u0026gt;next = tmp-\u0026gt;next; // delete nth; return dummyHead-\u0026gt;next; } }; 3.Leetcode面试题02.07:链表相交 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci\n(1)题目 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。\n图示两个链表在节点 c1 开始相交:\n题目数据保证整个链式结构中不存在环。\n注意,函数返回结果后,链表必须保持其原始结构 。\n示例 1:\n1 2 3 4 5 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 输出:Intersected at \u0026#39;8\u0026#39; 解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。 从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。 在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 示例 2:\n1 2 3 4 5 输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 输出:Intersected at \u0026#39;2\u0026#39; 解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。 从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。 在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。 示例 3:\n1 2 3 4 5 输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 输出:null 解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。 由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。 这两个链表不相交,因此返回 null 。 提示:\nlistA 中节点数目为 m listB 中节点数目为 n 0 \u0026lt;= m, n \u0026lt;= 3 * 104 1 \u0026lt;= Node.val \u0026lt;= 105 0 \u0026lt;= skipA \u0026lt;= m 0 \u0026lt;= skipB \u0026lt;= n 如果 listA 和 listB 没有交点,intersectVal 为 0 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1] 进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?\n(2)思路 根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。\n那么在算法中如何实现呢,那么只需要先分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键所在啦。\n先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* curA = headA; ListNode* curB = headB; int lenA = 0, lenB = 0; while (curA != NULL) { // 求链表A的长度 lenA++; curA = curA-\u0026gt;next; } while (curB != NULL) { // 求链表B的长度 lenB++; curB = curB-\u0026gt;next; } curA = headA; curB = headB; // 让curA为最长链表的头,lenA为其长度 if (lenB \u0026gt; lenA) { swap (lenA, lenB); swap (curA, curB); } // 求长度差 int gap = lenA - lenB; // 让curA和curB在同一起点上(末尾位置对齐) while (gap--) { curA = curA-\u0026gt;next; } // 遍历curA 和 curB,遇到相同则直接返回 while (curA != NULL) { if (curA == curB) { return curA; } curA = curA-\u0026gt;next; curB = curB-\u0026gt;next; } return NULL; } }; 时间复杂度:O(n+m) 空间复杂度:O(1) 4.Leetcode142:环形链表II 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/linked-list-cycle-ii\n(1)题目 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。\n如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。\n不允许修改链表。\n示例 1:\n1 2 3 输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。 示例 2:\n1 2 3 输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。 示例 3:\n1 2 3 输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。 提示:\n链表中节点的数目范围在范围 [0, 104] 内 -105 \u0026lt;= Node.val \u0026lt;= 105 pos 的值为 -1 或者链表中的一个有效索引 进阶:你是否可以使用 O(1) 空间解决此题?\n(2)思路 对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。\n对于这道题我们需要解决以下两点:\n如何判断链表有环 如果有环,怎么找到这个环的入口 \u0026lt;1\u0026gt;如何判断链表有环\n对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点,如果fast指针和slow指针在中途相遇,则说明存在环形链表。\n由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:\n\u0026lt;2\u0026gt;如果有环,怎么找到这个环的入口\n既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。\n假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。\n当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果,那么据此我们可以得出以下结论:\n1.slow指针走过的节点数 = x + y\n2.fast指针走过的节点数 = x + y + n*(y+z)\tn:代表slow指针进入环形链表后,此时fast指针在环中的循环次数\n3.得到等式:x + y = x + y + n*(y+z)\t此处需要注意:n \u0026gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍\n4.我们的目标为x,因此化简上式:x = n (y + z) - y\n5.当n等于1时,我们可以得知上式结果为:x = z,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。\n6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点\n动画如下:\n上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?\n其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode* fast = head; ListNode* slow = head; while(fast != NULL \u0026amp;\u0026amp; fast-\u0026gt;next != NULL) { slow = slow-\u0026gt;next; fast = fast-\u0026gt;next-\u0026gt;next; // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 if (slow == fast) { ListNode* index1 = fast; ListNode* index2 = head; while (index1 != index2) { index1 = index1-\u0026gt;next; index2 = index2-\u0026gt;next; } return index2; // 返回环的入口 } } return NULL; } }; 5.链表总结 图片来源: 代码随想录知识星球成员:海螺人\n","date":"2023-02-18T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover_hu7bf0cb3ae68de70cd5a7fa616f644222_131543_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/","title":"【数据结构与算法】链表2:节点交换与删除 \u0026 链表相交 \u0026 环形链表"},{"content":"今日任务 链表理论基础\n203.移除链表元素\n707.设计链表\n206.反转链表\n1.链表理论基础 (1)什么是链表? 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。\n链表的入口节点称为链表的头节点也就是head。\n(2)链表的类型 常见的链表类型有以下几种:\n\u0026lt;1\u0026gt;单链表\n单向链表是一种包含两部分的数据结构,即一个是数据部分(数据域),另一个是地址部分(指针域),其中包含下一个或后继节点的地址。节点中的地址部分也称为指针。\n在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为头指针。\n由于单链表的指针域只保存了下一个节点的地址,因此在单链表中,只能向前遍历,而不能反向遍历。\n1 2 3 4 5 6 7 // 单向链表中节点的表示 struct node { int data; struct node *next; } \u0026lt;2\u0026gt;双链表\n前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。\n这就意味着,双向链表不仅支持向前查询,还可以向后查询。\n1 2 3 4 5 6 7 8 // 双向链表中节点的表示 struct node { int data; struct node *next; struct node *prev; } \u0026lt;3\u0026gt;循环链表\n循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,循环链表没有起始节点和结束节点,我们可以朝任意方向进行遍历(向前或者向后)。\n1 2 3 4 5 6 7 // 循环链表中节点的表示 struct node { int data; struct node *next; } 乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。\n(3)链表的存储方式 前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。\n在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。\n(4)链表的定义 给出链表节点的定义:\n1 2 3 4 5 6 // 单链表 strcut ListNode{ int val;\t//节点上存储的元素 ListNode *next;\t//指向下一个节点的指针 ListNode(int x): val(x),next(NULL){}\t// 节点的构造函数 }; 下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):\n1、通过自己定义构造函数初始化节点:\n1 ListNode* head = new ListNode(5); 2、使用默认构造函数初始化节点:\n1 2 ListNode* head = new ListNode(); head-\u0026gt;val = 5; 从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。\n(5)链表的操作 \u0026lt;1\u0026gt;删除节点\n我们以下图为例,目的时删除D节点:\n具体操作:\nC节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要将C节点的next指针指向E节点就可以了。\n此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。\n\u0026lt;2\u0026gt;添加节点\n在下图中,我们需要在C节点和D节点中添加一个F节点:\n添加F节点,只需要将C节点的next指针指向F节点,同时F节点的next指针指向D节点,这样就完成了节点的添加。\n(6)性能分析 这里我们将链表和数组做一个对比,详见下图:\n数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。 链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少 2.Leetcode203:移除链表元素 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/remove-linked-list-elements\n(1)题目 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。\n示例 1:\n1 2 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5] 示例 2:\n1 2 输入:head = [], val = 1 输出:[] 示例 3:\n1 2 输入:head = [7,7,7,7], val = 7 输出:[] 提示:\n列表中的节点数目在范围 [0, 104] 内 1 \u0026lt;= Node.val \u0026lt;= 50 0 \u0026lt;= val \u0026lt;= 50 (2)思路 案例1:\n链表:1-\u0026gt;4-\u0026gt;2-\u0026gt;4\t目的:移除元素4\n其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。\n那么此外我们还需要完成节点4的内存回收工作!\n案例二:\n由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。\n对于链表的操作有两种形式:\n1.直接使用原来的链表进行删除操作。 2.设置一个虚拟头节点再进行删除操作。 \u0026lt;操作1\u0026gt;:直接使用原来的链表进行移除\n移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。\n那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。\n对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。\n\u0026lt;操作2\u0026gt;:设置一个虚拟头节点再进行删除操作\n如何设置虚拟头节点,首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4。\n具体实现我们详见代码。\n(3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // 操作1实现:直接使用原来的链表进行删除操作 class Solution { public: ListNode* removeElements(ListNode* head, int val) { // 删除头结点 while (head != NULL \u0026amp;\u0026amp; head-\u0026gt;val == val) { // head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 ListNode* tmp = head; head = head-\u0026gt;next; delete tmp;\t// 此处需要对旧的头节点进行内存回收 } // 删除非头结点 ListNode* cur = head;\t// 当前节点 while (cur != NULL \u0026amp;\u0026amp; cur-\u0026gt;next!= NULL) { // cur-\u0026gt;next!= NULL:这里是同样的道理,不可操作空指针 if (cur-\u0026gt;next-\u0026gt;val == val) { ListNode* tmp = cur-\u0026gt;next; cur-\u0026gt;next = cur-\u0026gt;next-\u0026gt;next; delete tmp; } else { cur = cur-\u0026gt;next; } } return head; } }; 这里需要注意几点:\n对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错 操作1的关键代码就是下面的这两部分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // 操作2实现:设置一个虚拟头节点再进行删除操作 class Solution { public: ListNode* removeElements(ListNode* head, int val) { ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点 dummyHead-\u0026gt;next = head; // 将虚拟头结点指向head,这样方面后面做删除操作 ListNode* cur = dummyHead; while (cur-\u0026gt;next != NULL) { if(cur-\u0026gt;next-\u0026gt;val == val) { ListNode* tmp = cur-\u0026gt;next; cur-\u0026gt;next = cur-\u0026gt;next-\u0026gt;next; delete tmp; } else { cur = cur-\u0026gt;next; } } head = dummyHead-\u0026gt;next; delete dummyHead; return head; } }; 3.Leetcode707:设计链表 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/design-linked-list\n(1)题目 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。\n在链表类中实现这些功能:\nget(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。 示例:\n1 2 3 4 5 6 7 MyLinkedList linkedList = new MyLinkedList(); linkedList.addAtHead(1); linkedList.addAtTail(3); linkedList.addAtIndex(1,2); //链表变为1-\u0026gt; 2-\u0026gt; 3 linkedList.get(1); //返回2 linkedList.deleteAtIndex(1); //现在链表是1-\u0026gt; 3 linkedList.get(1); //返回3 提示:\n0 \u0026lt;= index, val \u0026lt;= 1000 请不要使用内置的 LinkedList 库。 get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。 (2)思路 分析题目给出的要求,主要是需要完成以下功能:\n获取链表第index个节点的值 在链表的最前面插入一个节点 在链表的最后面插入一个节点 在链表第index个节点面前插入一个节点 删除链表的第index个节点 (3)代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 class MyLinkedList { public: // 定义链表节点结构体 struct LinkedNode { int val; LinkedNode* next; LinkedNode(int val):val(val), next(nullptr){} }; // 初始化链表 MyLinkedList() { _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 _size = 0; } // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 int get(int index) { if (index \u0026gt; (_size - 1) || index \u0026lt; 0) { return -1; } LinkedNode* cur = _dummyHead-\u0026gt;next; while(index--){ // 如果--index 就会陷入死循环 cur = cur-\u0026gt;next; } return cur-\u0026gt;val; } // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 // 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 void addAtHead(int val) { LinkedNode* newNode = new LinkedNode(val); newNode-\u0026gt;next = _dummyHead-\u0026gt;next; _dummyHead-\u0026gt;next = newNode; _size++; } // 在链表最后面添加一个节点 void addAtTail(int val) { LinkedNode* newNode = new LinkedNode(val); LinkedNode* cur = _dummyHead; while(cur-\u0026gt;next != nullptr){ cur = cur-\u0026gt;next; } cur-\u0026gt;next = newNode; _size++; } // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 // 如果index大于链表的长度,则返回空 // 如果index小于0,则在头部插入节点 void addAtIndex(int index, int val) { if(index \u0026gt; _size) return; if(index \u0026lt; 0) index = 0; LinkedNode* newNode = new LinkedNode(val); LinkedNode* cur = _dummyHead; while(index--) { cur = cur-\u0026gt;next; } newNode-\u0026gt;next = cur-\u0026gt;next; cur-\u0026gt;next = newNode; _size++; } // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 void deleteAtIndex(int index) { if (index \u0026gt;= _size || index \u0026lt; 0) { return; } LinkedNode* cur = _dummyHead; while(index--) { cur = cur -\u0026gt;next; } LinkedNode* tmp = cur-\u0026gt;next; cur-\u0026gt;next = cur-\u0026gt;next-\u0026gt;next; delete tmp; _size--; } // 打印链表 void printLinkedList() { LinkedNode* cur = _dummyHead; while (cur-\u0026gt;next != nullptr) { cout \u0026lt;\u0026lt; cur-\u0026gt;next-\u0026gt;val \u0026lt;\u0026lt; \u0026#34; \u0026#34;; cur = cur-\u0026gt;next; } cout \u0026lt;\u0026lt; endl; } private: int _size; LinkedNode* _dummyHead; }; 4.Leetcode206:反转链表 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/reverse-linked-list\n(1)题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。\n示例 1:\n1 2 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2:\n1 2 输入:head = [1,2] 输出:[2,1] 示例 3:\n1 2 输入:head = [] 输出:[] 提示:\n链表中节点的数目范围是 [0, 5000] -5000 \u0026lt;= Node.val \u0026lt;= 5000 进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?\n(2)思路 链表的反转,只需要改变next指针的指向即可。\n(3)双指针法 对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。\ncur指针,指向链表的头节点 pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* temp; // 作为一个临时节点,保存cur的下一个节点 ListNode* cur = head; ListNode* pre = NULL;\t// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL // 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur while(cur) { temp = cur-\u0026gt;next; // 保存一下 cur的下一个节点,因为接下来要改变cur-\u0026gt;next cur-\u0026gt;next = pre; // 翻转操作 // 更新pre 和 cur指针 pre = cur; cur = temp; } return pre;\t// 返回的是新链表的头节点pre } }; (4)递归法 前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有自前向后递归、以及自后向前递归两种方法。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 递归法:自前向后 class Solution { public: ListNode* reverse(ListNode* pre,ListNode* cur){ if(cur == NULL) return pre; ListNode* temp = cur-\u0026gt;next; cur-\u0026gt;next = pre; // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 // pre = cur; // cur = temp; return reverse(cur,temp); } ListNode* reverseList(ListNode* head) { // 和双指针法初始化是一样的逻辑 // ListNode* cur = head; // ListNode* pre = NULL; return reverse(NULL, head); } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // 递归法:自后向前 class Solution { public: ListNode* reverseList(ListNode* head) { // 边缘条件判断 if(head == NULL) return NULL; if (head-\u0026gt;next == NULL) return head; // 递归调用,翻转第二个节点开始往后的链表 ListNode *last = reverseList(head-\u0026gt;next); // 翻转头节点与第二个节点的指向 head-\u0026gt;next-\u0026gt;next = head; // 此时的 head 节点为尾节点,next 需要指向 NULL head-\u0026gt;next = NULL; return last; } }; ","date":"2023-02-17T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover_hu0ba98275d6445c79f820f07c37ff307c_140407_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/","title":"【数据结构与算法】链表1:移除链表 \u0026设计链表\u0026链表反转(双指针法、递归法)"},{"content":"今日任务 977.有序数列的平方\n209.长度最小的子数组\n59.螺旋矩阵II\n1.Leetcode977:有序数列的平方 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/squares-of-a-sorted-array\n(1)题目 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。\n示例 1:\n1 2 3 4 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 示例 2:\n1 2 输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121] 提示:\n1 \u0026lt;= nums.length \u0026lt;= 104 -104 \u0026lt;= nums[i] \u0026lt;= 104 nums 已按 非递减顺序 排序 进阶:\n请你设计时间复杂度为 O(n) 的算法解决本问题\n(2)思路 最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。\n(3)暴力排序 有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:\n1 2 3 4 5 6 7 8 9 10 11 class Solution { public: vector\u0026lt;int\u0026gt; sortedSquares(vector\u0026lt;int\u0026gt;\u0026amp; nums) { for(int i = 0; i \u0026lt; nums.size(); i++){ // nums[i] = pow(abs(nums[i]),2); nums[i] *= nums[i]; } sort(nums.begin(),nums.end()); return nums; } }; 说明:\npow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)\u0026mdash;\u0026gt;2^2=4; abs(n):对n求绝对值 解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)\n**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **\n(4)双指针法 根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。\n定义一个新数组result,和数组A一样的大小,让K指向result数组终止位置 如果A[i] *A[i] \u0026lt; A[j] * A[j],那么result[k\u0026ndash;] = A[j] * A[j]; 如果A[i] *A[i] \u0026gt; A[j] * A[j],那么result[k\u0026ndash;] = A[i] * A[i]; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public: vector\u0026lt;int\u0026gt; sortedSquares(vector\u0026lt;int\u0026gt;\u0026amp; nums) { vector\u0026lt;int\u0026gt; result(nums.size(),0); int k = nums.size() - 1; for(int i = 0,j = nums.size() - 1; i \u0026lt;= j; ){ if(nums[i] * nums[i] \u0026lt; nums[j] * nums[j]){ result[k--] = nums[j] * nums[j]; j--; } else{ result[k--] = nums[i] * nums[i]; i++; } } return result; } }; 通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!\n2.Leetcode209:长度最小的子数组 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum\n(1)题目 给定一个含有 n 个正整数的数组和一个正整数 target 。\n找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, \u0026hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。\n示例 1:\n1 2 3 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。 示例 2:\n1 2 输入:target = 4, nums = [1,4,4] 输出:1 示例 3:\n1 2 输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0 提示:\n1 \u0026lt;= target \u0026lt;= 109 1 \u0026lt;= nums.length \u0026lt;= 105 1 \u0026lt;= nums[i] \u0026lt;= 105 进阶:\n如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。\n(2)思路 首先分析题意,最明显的就是要求是连续子数组,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。\n(3)暴力排序 对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public: int minSubArrayLen(int target, vector\u0026lt;int\u0026gt;\u0026amp; nums) { int result = INT32_MAX; // 最终的结果 int sum = 0; // 子序列的数值之和 int subLength = 0; // 子序列的长度 for (int i = 0; i \u0026lt; nums.size(); i++) { // 设置子序列起点为i sum = 0; for (int j = i; j \u0026lt; nums.size(); j++) { // 设置子序列终止位置为j sum += nums[j]; if (sum \u0026gt;= target) { // 一旦发现子序列和超过了s,更新result subLength = j - i + 1; // 取子序列的长度 result = result \u0026lt; subLength ? result : subLength; break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break } } } // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 return result == INT32_MAX ? 0 : result; } }; 时间复杂度:O(n^2) 空间复杂度:O(1) 对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。\n(4)滑动窗口 所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。\n那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。\n这里放上Carl大神的一张图,方便大家理解:\n那么最重要的两点来了:\n如何确定移动窗口的起始位置 如何确定移动窗口的结束位置 解答如下:\n窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动 窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public: int minSubArrayLen(int target, vector\u0026lt;int\u0026gt;\u0026amp; nums) { int result = INT32_MAX; int sum = 0; // 滑动窗口数值之和 int i = 0; // 滑动窗口起始位置 int subLength = 0; // 滑动窗口的长度 for (int j = 0; j \u0026lt; nums.size(); j++) { sum += nums[j]; // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 while (sum \u0026gt;= target) { subLength = (j - i + 1); // 取子序列的长度 result = result \u0026lt; subLength ? result : subLength; sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) } } // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 return result == INT32_MAX ? 0 : result; } }; 在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)\n3.Leetcode59:螺旋矩阵II 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/spiral-matrix-ii\n(1)题目 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。\n示例 1:\n1 2 输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]] 示例 2:\n1 2 输入:n = 1 输出:[[1]] 提示:\n1 \u0026lt;= n \u0026lt;= 20 (2)思路 在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持循环不变量原则。\n那么我们在模拟顺时针画矩阵时,遵循以下规则:\n填充上行从左往右 填充右列从上往下 填充下行从右往左 填充左列从下往上 也就是如下图所示,好好理解一下!\n回到题目,对于这种螺旋矩阵,我们首先要明确的坚持循环不变量原则,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。\n这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的1、3、5、7,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。\n(3)二分法求解 直接看代码部分:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Solution { public: vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; generateMatrix(int n) { vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt; res(n, vector\u0026lt;int\u0026gt;(n, 0)); // 使用vector定义一个二维数组 int startx = 0, starty = 0; // 定义每循环一个圈的起始位置 int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) int count = 1; // 用来给矩阵中每一个空格赋值 int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位 int i,j; while (loop --) { i = startx; j = starty; // 下面开始的四个for就是模拟转了一圈 // 模拟填充上行从左到右(左闭右开) for (j = starty; j \u0026lt; n - offset; j++) { res[startx][j] = count++; } // 模拟填充右列从上到下(左闭右开) for (i = startx; i \u0026lt; n - offset; i++) { res[i][j] = count++; } // 模拟填充下行从右到左(左闭右开) for (; j \u0026gt; starty; j--) { res[i][j] = count++; } // 模拟填充左列从下到上(左闭右开) for (; i \u0026gt; startx; i--) { res[i][j] = count++; } // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) startx++; starty++; // offset 控制每一圈里每一条边遍历的长度 offset += 1; } // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 if (n % 2) { res[mid][mid] = count; } return res; } }; 4.总结 图片来源: 代码随想录知识星球成员:海螺人\n","date":"2023-02-16T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover_hu0ba98275d6445c79f820f07c37ff307c_129507_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/","title":"【数据结构与算法】数组2:双指针法 \u0026 二分法(螺旋矩阵)"},{"content":"今日任务 数组理论基础\n704.二分查找\n27.移除元素\n1.数组理论基础 (1)数组是存放在连续内存空间上的相同类型数据的集合。\n注意:\n数组下标都是从0开始的 数组内存空间的地址是连续的 (2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。\n例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:\n(3)数组的元素是不能删除的,只能使用覆盖的方式。\n(4)C++中二维数组在地址空间上是连续的。\n通过编写一个程序来验证:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include \u0026lt;iostream\u0026gt; using namespace std; void test_arr(){ int array[2][3] = { {0,1,2}, {3,4,5} }; cout \u0026lt;\u0026lt; \u0026amp;array[0][0] \u0026lt;\u0026lt; \u0026#34; \u0026#34;\u0026lt;\u0026lt; \u0026amp;array[0][1] \u0026lt;\u0026lt;\u0026#34; \u0026#34;\u0026lt;\u0026lt; \u0026amp;array[0][2] \u0026lt;\u0026lt;endl; cout \u0026lt;\u0026lt; \u0026amp;array[1][0] \u0026lt;\u0026lt; \u0026#34; \u0026#34;\u0026lt;\u0026lt; \u0026amp;array[1][1] \u0026lt;\u0026lt;\u0026#34; \u0026#34;\u0026lt;\u0026lt; \u0026amp;array[1][2] \u0026lt;\u0026lt;endl; } int main() { test_arr(); } 在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节\n2.Leetcode704:二分查找 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/binary-search\n(1)题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。\n示例 1:\n1 2 3 输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4 示例 2:\n1 2 3 输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1 提示:\n你可以假设 nums 中的所有元素是不重复的。 n 将在 [1, 10000]之间。 nums 的每个元素都将在 [-9999, 9999]之间。 (2)思路 首先确定关键词:\n数组为有序数组 数组无重复元素 根据题目和提示,我们联想到二分法。\n(3)二分法 简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。\n关于二分法的写法,区间的定义一般分为两种:\n左闭右闭 [left, right] 左闭右开 [left, right) 根据二分法的两种写法,我们分别求解:\n\u0026lt;1\u0026gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]\n区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:\nwhile(left \u0026lt;= right) 要使用 \u0026lt;=,因为left == right 是有意义的,所以使用 \u0026lt;= if (nums[middle] \u0026gt; target) right要赋值为middle-1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // 下面是一段伪代码形式来讲解 首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值: Left | Right | Middle | target 很明显 Left = 数组下标0\t而Right为 NumSize(array)-1\tMiddle = (Left + Right) / 2 所以编写如下函数: //\t因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 while(left \u0026lt;= right)\t{ // 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 if(Num(middle) \u0026gt; Num(target)) Num(right) = Num(middle) - 1; // 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 else if(Num(middle) \u0026lt; Num(target)) Num(left) = Num(middle) + 1; // 那么第三种情况也就是middle直接等于target,返回即可 else return middle; } return -1; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 版本一 class Solution { public: int search(vector\u0026lt;int\u0026gt;\u0026amp; nums, int target) { int left = 0; int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right] while (left \u0026lt;= right) { // 当left==right,区间[left, right]依然有效,所以用 \u0026lt;= int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2 if (nums[middle] \u0026gt; target) { right = middle - 1; // target 在左区间,所以[left, middle - 1] } else if (nums[middle] \u0026lt; target) { left = middle + 1; // target 在右区间,所以[middle + 1, right] } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } }; \u0026lt;2\u0026gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)\n根据左闭右开的方式,那么处理方式有如下两点:\nwhile(left \u0026lt; right),这里使用 \u0026lt;,因为left == right在区间 [left, right)是没有意义的 if(Num(middle) \u0026gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // 下面是一段伪代码形式来讲解 // 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: Left | Right | Middle | target 上面的定义不变,但是函数主体需要有一些改动了 //\t注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), while(left \u0026lt; right)\t{ // 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) if(Num(middle) \u0026gt; Num(target)) Num(right) = Num(middle); // 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 else if(Num(middle) \u0026lt; Num(target)) Num(left) = Num(middle) + 1; // 那么第三种情况也就是middle直接等于target,返回即可 else return middle; } return -1; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 版本二 class Solution { public: int search(vector\u0026lt;int\u0026gt;\u0026amp; nums, int target) { int left = 0; int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right) while (left \u0026lt; right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 \u0026lt; int middle = left + ((right - left) \u0026gt;\u0026gt; 1); if (nums[middle] \u0026gt; target) { right = middle; // target 在左区间,在[left, middle)中 } else if (nums[middle] \u0026lt; target) { left = middle + 1; // target 在右区间,在[middle + 1, right)中 } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } }; 上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:\n解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2\n解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。\n解析二:int middle = left + ((right - left) \u0026gt;\u0026gt; 1);\n解答:\u0026gt;\u0026gt;是位运算的符号,\u0026gt;\u0026gt;1代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11\u0026raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。\n此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为移位指令占2个机器周期,而乘除法指令占4个机器周期。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。\n3.Leetcode27:移除元素 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/remove-element\n(1)题目 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。\n不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。\n元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。\n说明:\n为什么返回数值是整数,但输出的答案是数组呢?\n请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。\n你可以想象内部操作如下:\n1 2 3 4 5 6 7 8 // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 int len = removeElement(nums, val); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i \u0026lt; len; i++) { print(nums[i]); } 示例 1:\n1 2 3 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 示例 2:\n1 2 3 输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3] 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。 提示:\n0 \u0026lt;= nums.length \u0026lt;= 100 0 \u0026lt;= nums[i] \u0026lt;= 50 0 \u0026lt;= val \u0026lt;= 100 (2)思路 首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。\n对此我们使用暴力解法\n(3)暴力解法 解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution{ public: int removeElement(vector\u0026lt;int\u0026gt;\u0026amp; nums, int val){ int size = nums.size(); for(int i = 0; i \u0026lt; size; i++){ if(nums[i] == val){\t// 发现需要移除的元素,就将数组集体向前移动一位 for(int j = i + 1; j \u0026lt; size; j++){\tnums[j - 1] = nums[j]; } i--;\t// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 size--;\t// 相对应的数组大小-1 } } return size; } }; 说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。\n(4)双指针法 除了暴力解法,双指针法也同样适用于此场景。\n通过定义两个指针,一个slow指针和一个fast指针, 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。\nfast指针:寻找新数组的元素,新数组就是不含有目标元素的数组 slow指针:指向更新 新数组下标的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 时间复杂度:O(n) // 空间复杂度:O(1) class Solution { public: int removeElement(vector\u0026lt;int\u0026gt;\u0026amp; nums, int val) { int slowIndex = 0; for (int fastIndex = 0; fastIndex \u0026lt; nums.size(); fastIndex++) { if (val != nums[fastIndex]) {\t// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 nums[slowIndex++] = nums[fastIndex]; } // 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 } return slowIndex; } }; ","date":"2023-02-15T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover_hu0e8d2fd03c332bd70a4cc1eeffe2ac5d_135444_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/","title":"【数据结构与算法】数组1:二分查找 \u0026 移除元素"},{"content":"简单了解Micropython MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。\nRT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。\nMicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。\nMicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。\nMicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。\n开发环境 VScode Keil(v5.38.0.0) RT-Thread MicroPython IDE(VScode插件搜索) ENV v1.4.0(可点击链接下载) 初步移植 首先从RT-Thread官方仓库克隆master分支的仓库到本地\n来到该目录:.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk,鼠标右键打开ENV工具,首先打开命令行菜单\n1 menuconfig 使能添加Micropython软件包:RT-Thread Online Packages---\u0026gt;launage packages---\u0026gt;Micropython\nHeap size修改为20480(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)\n进入Hardware Module,使能machine uart\n同时我们回到主菜单界面,进入Hardware Drives config---\u0026gt;on-chip Peripheral Drivers,使能UART0和UART2\n由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面RT-Thread Components---\u0026gt;set main thread stack size修改为8192\n保存退出,并使用命令下载软件包:\n1 pkgs --update 使用ENV生成MDK工程:\n1 scons --target=mdk5 BUG修复 双击打开project.uvprojx,进行编译\n这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\packages\\micropython-v1.13.0\\SConscript\n切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:\n1 scons --target=mdk5 此时编译错误大大减少,只剩下三个错误:\n第一个错误需要在菜单中使能Support legacy version for compatibility(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件\n重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明\n找到头文件所在位置:.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk\\packages\\micropython-v1.13.0\\port\\mpgetcharport.h\n此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此PR,所以解决该问题就是重新定义一下DFS_FD_OFFSET\n想不到编译之后居然还有一个错误,这里参考这位开发者的issue,将list_mem();注释(此处可能是个官方BUG,后续尝试修复)\n最后发现,终于没有错误啦!!!\nRT-Thread Micropython环境搭建 VScode扩展搜索下载RT-Thread Micropython\n创建工程 vscode下方导航栏点击创建Micropython工程,创建一个新的MicroPython工程,并选择工程存放路径\n上电测试Micropython 点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO\n测试示例 LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行\nMicropython测试 Finsh控制台输入python,转到python控制台,同时还支持quit()、exit()命令退回Finsh控制台\n简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module\n打开图形化菜单进入该路径下:RT-Thread online packages--\u0026gt;launage packages---\u0026gt;system module,使能uos:basic 'operating system' services 同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!\n结语 搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!\n联系 Email :yifang.wangyq@foxmail.com Github Address :https://github.com/kurisaW My Website :https://kurisaw.github.io ","date":"2023-02-06T00:00:00Z","image":"https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover_hu1d41c96ada7dcbd0b71542fef1eff150_4218_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/","title":"【NXP】LPC55S69-Micropython移植日志"},{"content":"前言 前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。\n开始测试 首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:.\\rt-thread\\bsp\\lpc55sxx\\lpc55s69_nxp_evk,首先使用RT-Thread的ENV工具生成MDK工程:\n1 scons --target=mdk5 这里建议大家使用最新版ENV工具。然后双击打开project.uvprojx工程,点击重新编译。\n但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。\nBUG分析与解决 首先先看一下我的keil版本为V5.25:\n听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)\n此处附上Keil最新版下载官网\n下载好最新版本后,前面的步骤重复,然后重新编译下载即可。\n项目演示 下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:\n结语 本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。\n联系 Email :yifang.wangyq@foxmail.com Github Address :https://github.com/kurisaW My Website :https://kurisaw.github.io/ ","date":"2023-02-05T00:00:00Z","image":"https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover_hu31f054e617ccf5275f397086d95972c2_413191_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/","title":"【NXP】LPC55S69初上手"},{"content":"前期准备 资料:\nMCUXpresso_IDE_User_Guide.pdf 开发环境(官方直链)\nMCUXpresso Config Tools MCUXpresso IDE SDK代码包 MCUXpresso Config Tools和MCUXpresso IDE的安装不再赘述,下面是SDK代码包的安装教学\n1.选择开发板\u0026ndash;\u0026gt;\n2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)\n3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击下载SDK\n4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包\n5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载\nIDE配置 完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开MCUXpresso IDE,在主界面的下方栏可以看到有一个Installed SDKs,准备好刚刚下载的SDK代码包,导入其中\n之后我们就可以使用这个SDK代码包去创建一个新的工程了。\n工程导入 这里我们简单做个示范,选择导入示例工程\n选择指定的开发板后点击下一步\n在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可\n工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译\nMCUXpresso IDE有两个地方都可以启动调试,选择一个习惯的即可\n配置工具使用 和MCUXpresso IDE配套的还有MCUXpresso Config Tools,打开MCUXpresso IDE,找到配置工具按钮打开\n结语 到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!\n联系 Email :yifang.wangyq@foxmail.com Github Address :https://github.com/kurisaW My Website :https://kurisaw.github.io/ ","date":"2023-02-04T00:00:00Z","image":"https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover_hu63ed3deabe1b375a8669082d0efcf2de_379910_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/","title":"【NXP】LPC55S69开发环境搭建"},{"content":"开发环境 软件\nubuntu20.04 VMware Workstation 硬件\nRDC2022纪念版开发板 全志D1s芯片 材料下载 首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。\n1 git clone https://github.com/RT-Thread/userapps.git 在userapps目录下克隆RT-Thread仓库代码\n1 git clone https://github.com/RT-Thread/rt-thread.git Riscv工具链配置 进入userapps/tools,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到 userapps\\tools\\gun_gcc 目录。\n1 python3 get_toolchain.py riscv64 返回上一级,刷新工具链环境,同时记住这里的EXEC_PATH工具链路径,后面需要修改为此路径\n1 2 cd .. source smart-env.sh riscv64 内核环境编译 scons安装 环境编译会用到scons,所以我们先下载scons\n1 sudo apt install scons 查看scons版本信息可判断是否安装成功\nenv工具安装 依次执行以下程序:\n1 2 3 scons --menuconfig source ~/.env/env.sh pkgs --update 内核编译 使用 scons 命令进行编译,编译成功后会在 userapps/rt-thread/bsp/allwinner/d1s 目录下生成 sd.bin,这个文件就是我们需要烧录到开发板中的文件,它包括了 uboot.dtb,opensbi,rtthread.bin。\n1 scons 此时直接编译会报错,因为工具链路径还没有修改\n我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径\n再次执行scons命令编译\n程序烧录 我这里采用的是从TF卡作为启动方式。\n1、首先准备一张容量在128G的空白TF卡\n2、格式化TF卡,并使用ubuntu的gparted工具重新分区\n如果没有下载该工具可使用下面的命令进行下载:\n1 sudo apt install gparted 启动该工具\n1 sudo gparted 这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32\n3、接下来进行程序的烧录\n首先进入userapps/rt-thread/bsp/allwinner/d1s/tools,执行命令:\n1 sudo dd if=boot0_sdcard_sun20iw1p1_d1s.bin of=/dev/sdb bs=1024 seek=8 返回上一级,再次执行命令:\n1 sudo dd if=sd.bin of=/dev/sdb bs=1024 seek=56 到此烧录工作已完成。\n启动RT-Smart 我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。\n此处注意串口波特率为500000\n简单测试下MSH命令:\n到此就测试结束啦,欢迎大家讨论交流。\n","date":"2023-01-19T00:00:00Z","image":"https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover_hu228c98d09717a8ebbae84ab2df7f6e1c_11576_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/","title":"RDC 2022纪念版开发板-D1S在RT-Smart运行"},{"content":"一、创建工程,选择SEGGER_RTT软件包 2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ] 在rt_console_set_device前调用rt_hw_jlink_rtt_init初始化函数\n3、控制台对接上jlinkRtt 1 2 3 rtconfg.h // 修改RT_CONSOLE_DEVICE_NAME为空 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 shell.c [ 路径:D:\\rt-thread\\components\\finsh\\shell.c] /* 1、首先添加以下头文件 */ #include \u0026#34;SEGGER_RTT.h\u0026#34; #include \u0026#34;SEGGER_RTT_Conf.h\u0026#34; /* 2、修改finsh_getchar */ int finsh_getchar(void) { #ifdef RT_USING_DEVICE char ch = 0; #ifdef RT_USING_POSIX_STDIO if(read(STDIN_FILENO, \u0026amp;ch, 1) \u0026gt; 0) { return ch; } else { return -1; /* EOF */ } #else rt_device_t device; RT_ASSERT(shell != RT_NULL); device = shell-\u0026gt;device; if (device == RT_NULL) { extern char rt_hw_console_getchar(void); return rt_hw_console_getchar(); } while (rt_device_read(device, -1, \u0026amp;ch, 1) != 1) { rt_sem_take(\u0026amp;shell-\u0026gt;rx_sem, RT_WAITING_FOREVER); if (shell-\u0026gt;device != device) { device = shell-\u0026gt;device; if (device == RT_NULL) { return -1; } } } return ch; #endif /* RT_USING_POSIX_STDIO */ #else extern char rt_hw_console_getchar(void); return rt_hw_console_getchar(); #endif /* RT_USING_DEVICE */ } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 kservice.c [ 路径:\\rt-thread\\src\\kservice.c ] // 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output RT_WEAK void rt_hw_console_output(const char *str) { /* empty console output */ rt_size_t i = 0, size = 0; size = rt_strlen(str); for (i = 0; i \u0026lt; size; i++) { if (*(str + i) == \u0026#39;\\n\u0026#39;) { break; } } SEGGER_RTT_printf(0,\u0026#34;%s\u0026#34;,str); } RTM_EXPORT(rt_hw_console_output); 4、实验效果 首先确保已经下载好J-Link RTT Viewer,直接去官网下载最新版本即可\n然后编译和下载工程,注意下载方式为J-Link\n双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看_SEGGER_RTT变量地址(全局搜索即可,找到.bss._SEGGER_RTT)\n打开J-Link RTT Viewer\n此时就可以正常使用segger_rtt了!\n","date":"2022-08-22T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/","title":"瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包"},{"content":"一、了解TortoiseGit TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。\n由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。\nTortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。\n它是在GPL下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。\n二、安装GIit及TortoiseGit Git下载官网: https://gitforwindows.org/index.html TortoiseGit下载官网:https://tortoisegit.org/download/ 同时下载语言包 当然这里也有百度网盘链接,也可点击下方链接进行下载\n链接:https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs 提取码:dzbs\n三、TortoiseGit配置 完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项\n这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文\n配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:\n点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):\n1 2 [credential] helper = store 完成后保存,关闭记事本,确定即可。\n则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。\n如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。\n四、添加GitHub SSH Keys及密钥上传 首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\\TortoiseGit\\bin\\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)\n然后复制下方公钥,\n打开github,完成下图操作:\n五、使用TortoiseGit提交代码到远端仓库 在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹\n鼠标右键可以看到选项Git在这里创建版本库,点击创建版本库\n鼠标右键打开TortoiseGit-\u0026gt;设置(Settings)-\u0026gt;Git-\u0026gt;远端(Remote),进行如下配置\n此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:\n我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:\n1 2 3 4 5 6 7 正常的:绿色的对号 被修改过的:红色感叹号 新添加的:蓝色的加号 未受控的(无版本控制的):蓝色的问号 忽略不受控的:灰色的减号 删除的:红色的x号 有冲突的:黄色的感叹号 鼠标右键添加文件\n注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次\n总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)\n添加-\u0026gt;提交-\u0026gt;拉取-\u0026gt;推送\n那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!\n","date":"2022-07-29T00:00:00Z","image":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/cover_hu3f010b25b875bbae5690e71033d3b645_14048_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/","title":"【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制"},{"content":"一、开发板配置 (使用secureCRT) 首先确保开发板完成以下配置:\n主机IP: set ipaddr192.168.1.10 服务器IP: set serverip 192.168.1.141 网关: set gatewayip 192.168.1.1 子网掩码: set netmask 255.255.255.0 内核驱动设置: set bootcmd 'tftp 30008000 zImage; bootm 30008000' bootargs配置: set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200\n最后输入save保存一下,这样开发板的网络和内核配置就设置好了\n二、了解rootfs rootfs的两种表现形式: 1、nfs方式启动的文件夹形式的rootfs(主机)\n2、用来烧录的镜像形式rootfs(开发板)\n三、虚拟机文件配置 1.目录配置 首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: rootfs x210_bsp\n这时候我们需要知道这两个文件夹下有什么:\nx210_bsp:用于uboot烧录和配置 rootfs:用于挂载开发板根文件系统 2.x210_bsp配置 首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压\n以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用\n3.rootfs配置 首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压\n以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件\n4.make menuconfig 进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单\n这里我们按下面操作完成网络配置\n1 2 [*]Networking support ---\u0026gt; Networking options ---\u0026gt; 网络文件系统设置\n1 2 File systems ---\u0026gt; [*]Networking File Systems ---\u0026gt; 有需要把开发板作为服务器端的也可以选择把NFS server support设置打开,这里我们仅实验客户端\n以上配置结束后输入命令make编译,至此开发板uboot的网络和文件系统部分配置结束。\n四、busybox的移植实战 1、了解busybox busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。\n2、busybox源码获取 busybox官网\n注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)\n3、busybox配置 (1)修改Makefile\n首先进入~/rootfs/x210_rootfs/busybox-1.24.1目录下\n输入命令vi Makefile进入脚本进行以下修改\n173行:CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi- 注意:此处的交叉编译链需要对照自己电脑的交叉编译链 191行:ARCH=arm\n(2)make menuconfig配置\nTip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。\nmake menuconfig\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Busybox Settings---\u0026gt; Build Options---\u0026gt; [*]Build BusyBox as a static binary(no shared libs) Busybox Library Tuning---\u0026gt; [*]vi-style line editing commands [*]Fancy shell prompts Linux Module Utilities---\u0026gt; [ ]Simplified modutils [*]insmod [*]rmmod [*]lsmod [*]modprobe [*]depmod Linux System Utilities---\u0026gt;[*]mdev [*]Support /etc/mdev.conf [*]Support subdirs/symlinks [*]Support regular expressions substitutions when renaming dev [*]Support command execution at device addition/removal [*]Support loading of firmwares 大家学习使用的时候跟着上面的进行配置即可 配置完成后,输入以下命令: make -j4 (4代表我主机的内核数) 无报错继续下一步: make install\n解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装\n(3)设置busybox安装路径\nmake menuconfig 1 2 3 Busybox Settings ---\u0026gt; Installation Options (\u0026#34;make install\u0026#34; behavior) ---\u0026gt; (./)BusyBox installation prefix) //这里设置安装路径 (4)解决方案 在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。\nmake -j4编译可能遇到的问题:\nsync.c(text.sync_main+0x78):undefined reference to 'syncfs' 分析:可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。\n解决方法:\nmake menuconfig 点击/进入搜索,输入SYNC,根据提示禁用SYNC 最后再make -j4编译一下即可\n其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。\n(5)make install简述\n默认安装位置:./_install 文件包含有:bin linuxrc sbin usr ls -l可以看到: linuxrc -\u0026gt; bin/busybox //这个linuxrc其实就是个符号链接 这里也不难发现,bin下的所有的符号链接都指向了busybox\n(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下\n1 2 3 4 make menuconfig Busybox Settings —\u0026gt; Installation Options (“make install” behavior) —\u0026gt; (/root/rootfs/x210_rootfs)BusyBox installation prefix 执行make install后,回到被挂载的目录下,可以发现这四个文件已经生成。\n五、NFS挂载根文件系统 1.NFS简述 NFS 是Network File System的缩写,即网络文件系统。 功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。 2.NFS服务器安装 sudo apt-get install nfs-kernel-server\n3.NFS使用过程 启动NFS服务器-\u0026gt;启动NFS客户端-\u0026gt;挂载NFS目录\n4.NFS配置 输入命令vim /etc/exports 在最后一行修改\n\u0026quot;文件挂载目录\u0026quot; *(rw,sync,no_root_squash,no_subtree_check) 保存退出后,输入mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs(根据实际情况修改) 输入命令/etc/init.d/nfs-kernel-server restart重启NFS服务 六、开发板根目录配置 首先将etc目录放置到挂载根目录下\netc目录下载:\n点击此处\n1.inittab文件详解 \u0026lt;1\u0026gt;添加一个典型的inittab文件到etc目录下\ninittab下载\n\u0026lt;2\u0026gt;inittab格式解析\nid:runlevels:action:process\n解释:\nid:标识符,即代表记录的名字 runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别 action:用于描述该级别该执行什么操作(部分说明) process:具体执行的命令 \u0026lt;3\u0026gt;了解busybox init与inittab之间的关系\nbusybox init进程主要完成系统的初始化工作。 busybox init进程的工作流程:\n为init设置信号处理过程-\u0026gt;初始化控制台-\u0026gt;剖析/etc/inittab文件-\u0026gt;执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS-\u0026gt;执行所有导致 init 暂停的 inittab 命令(动作类型: wait)-\u0026gt;执行所有仅执行一次的 inittab(动作类型: once)\n一旦完成以上工作, init 进程便会循环执行以下进程: \u0026lt;1\u0026gt;执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) \u0026lt;2\u0026gt;执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)\n简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。 注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。\n\u0026lt;4\u0026gt;配置 vi命令打开inittab模板文件\n1 2 3 4 5 6 7 8 9 10 11 12 #first:run the system script file 注释 ::sysinit:/etc/init.d/rcS //在控制台初始化之前执行rcS ::askfirst:-/bin/sh ::ctrlaltdel:-/sbin/reboot //执行控制台时的打印信息 #umount all filesystem //同时按住3键可以重启 ::shutdown:/bin/umount -a -r//关机时接触挂载init #restart init process//重启时启动 ::restart:/sbin/init 修改脚本: 2.rcS文件详解 \u0026lt;1\u0026gt;添加一个典型的rcS文件到etc目录下\nrcS下载\n\u0026lt;2\u0026gt;rcS文件解析\n1 2 3 4 5 6 7 8 9 10 11 #!/bin/sh 需要继续添加环境变量,在后面:/new 即可 PATH=/sbin:/bin:/usr/sbin:/usr/bin runlevel=S prevlevel=N umask 022 export PATH runlevel prevlevel mount -a PATH=xxx PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。\nrunlevel= linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启\numask= umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。\nmount -a mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)\n3.rcS实战 首先将前面提供的etc压缩包模板下载至共享文件夹\n\u0026lt;1\u0026gt;输入命令打开rcS脚本:vi etc/init.d/rcS。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了\n\u0026lt;2\u0026gt;mdev\nudev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。\nrcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在rcS文件中添加以下与mdev有关的2行配置项后:\n1 2 echo /sbin/mdev \u0026gt; /proc/sys/kernel/hotplug mdev -s 再次启动系统后发现/dev目录下生成了很多的设备驱动文件\n\u0026lt;3\u0026gt;hostname\n我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名\nhostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。\n添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname \u0026lt;4\u0026gt;ifconfig\n(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40\n\u0026lt;5\u0026gt;mount挂载测试\n这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如\n1 2 3 4 mount: mounting tmpfs on /var failed: No such file or directory mount: mounting tmpfs on /tmp failed: No such file or directory mount: mounting tmpfs on /dev failed: No such file or directory ...... 这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,输入mkdir命令在根目录依次创建即可。\n七、动态链接库的拷贝 1.静态编译链接测试 首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件\n1 2 3 4 5 6 7 8 a.c file-\u0026gt; #include\u0026lt;stdio.h\u0026gt; int main() { printf(\u0026#34;hello world!\\n\u0026#34;); return 0; } 2.解决办法: 拷贝一份动态链接库文件到开发板根目录下\n1 cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf 3.解释: 这时候执行命令./a.out发现可以正常打印\n4.strip工具 动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在传统的嵌入式系统中flash空间是有限的,为了节省空间常常把这些符号信息去掉。这样节省空间并且不影响运行。\n去掉符号信息的命令:\narm-linux-strip *so*\n八、ext2格式镜像烧录 1.\t确定文件夹格式的rootfs可用 前面我们已经提前配置好,此处不再赘述\n2.ext2镜像制作 首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。\n然后输入以下命令:\n1 2 3 4 5 6 7 dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240 losetup /dev/loop1 rootfs.ext2 mke2fs -m 0 /dev/loop1 10240 mount -t ext2 /dev/loop1 ./ext2_rootfs/ 此时我们复制一份开发板根目录到ext2_rootfs下 1 cp rootfs.ext2 /mnt/hgfs/Myshare/ -f 进入~/rootfs目录,执行清除卸载命令 1 2 umount /dev/loop1 losetup -d /dev/loop1 此时在rootfs目录下可以看见生成了一个rootfs.ext2镜像文件,我们将其复制到共享文件夹下,然后再将其复制到电脑fastboot目录下,执行uboot烧录操作,借鉴该博客【Linux系统开发】Study210开发板刷安卓系统 至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!\n参考资料:\nLinux开发之根文件系统构建及过程详解\nbusybox init进程和/etc/inittab关系\nNFS-LINUX挂载实践\n","date":"2022-07-28T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/","title":"x210开发板根目录文件系统构建"},{"content":"进程管理类 1.top命令\ntop命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。 top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。 2.htop命令\nhtop命令是top的改进版。 默认情况下,大多数Linux发行版本都没有安装htop。 htop命令显示的信息与top相同,但它的界面更人性化。 3.pstree\npstree命令也可以显示进程信息。 它以树的形式显示进程。 4.kill\nkill命令可以根据进程ID来杀死进程。 你可以使用ps -A,top,或者grep命令获取到进程ID。 从技术层面来讲,kill命令可以发送任何信号给一个进程。 你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。 文件操作类(基础篇) 新建文件:touch\n详细文档通过 man [command] 查看\n管理文件\nrm: 删除文件或目录(-r) mkdir 新建目录 cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r) mv 移动或重命名文件、目录 压缩tzip文件\nzip FileName.zip DirName # 将DirName本身压缩 zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩 解压zip文件\nunzip filename 查找含spark的目录、文件\nfind /home/jack -name \u0026lsquo;spark\u0026rsquo; 更改密码\npasswd 更改文件名或移动文件位置\n语句:mv oldFileName newFileName 示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt 删除文件\n删除文件: rm test.txt 删除空文件夹: rmdir test 删除非空文件夹及其目录下的所有文件夹及文件:rm -r test 删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt) 防火墙状态 首先需要输入安装命令: apt install ufw\n查看防火墙当前状态 sudo ufw status\n开启防火墙 sudo ufw enable\n关闭防火墙 sudo ufw disable\n查看防火墙版本 sudo ufw version\n默认允许外部访问本机 sudo ufw default allow\n默认拒绝外部访问主机 sudo ufw default deny\n允许外部访问443端口 sudo ufw allow 443\n拒绝外部访问443端口 sudo ufw deny 443\n允许某个IP地址访问本机所有端口 sudo ufw allow from 192.168.0.1\n网络设置 重置网卡 sudo /etc/init.d/networking restart\n","date":"2022-07-25T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/","title":"Ubuntu命令查看手册"},{"content":"\n1、项目介绍 本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。\n下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。\n2、前期准备 开发工具:\nRT-Thread Studio RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。\nRT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。\n下载链接:RT-Thread Studio 下载\n瑞萨FSP(灵活配置软件包) 瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。\n下载链接:瑞萨FSP v3.5.0\n模块:\nAHT10 ESP8266 RC522及读卡标签 ssd1306 OLED显示屏 3、模块介绍及使用 3.1 AHT10 3.1.1底层I2C通信协议简介 I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。\n而I2C通信的读写数据是通过等待从机的应答信号(ACK)。\n也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。\n这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。\n当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。\n简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。\n3.1.2 sensor框架的使用 在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。\n掌握sensor框架的使用,需要了解一下API的调用:\n函数 描述 rt_device_find() 根据传感器设备设备名称查找设备获取设备句柄 rt_device_open() 打开传感器设备 rt_device_read() 读取数据 rt_device_control() 控制传感器设备 rt_device_set_rx_indicate() 设置接收回调函数 rt_device_close() 关闭传感器设备 3.1.3 AHT10对接到sensor框架 首先先来介绍下接线:\n引脚功能 引脚接线 SCL P512 SDA P511 VCC 3.3V GND GND 然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动-\u0026gt;Enable I2C BUS-\u0026gt;使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能\n然后使用下面的程序完成模块初始化工作\n1 2 3 4 5 6 7 8 9 10 11 12 13 #include \u0026#34;sensor_asair_aht10.h\u0026#34; #define AHT10_I2C_BUS \u0026#34;i2c1\u0026#34; /* 模块初始化工作 */ static int rt_hw_aht10_port(void) { struct rt_sensor_config cfg; cfg.intf.dev_name = AHT10_I2C_BUS; cfg.intf.user_data = (void *)AHT10_I2C_ADDR; rt_hw_aht10_init(\u0026#34;aht10\u0026#34;, \u0026amp;cfg); return RT_EOK; } INIT_ENV_EXPORT(rt_hw_aht10_port); AHT10温湿度数据读取\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // AHT10设备读取数值 float humidity, temperature; aht10_device_t dev; rt_hw_aht10_port(); dev = aht10_init(AHT10_I2C_BUS); if (dev == RT_NULL) { rt_kprintf(\u0026#34; The sensor initializes failure\u0026#34;); } else { rt_kprintf(\u0026#34; The sensor initializes ok!\\n\u0026#34;); } /* read humidity 采集湿度 */ humidity = aht10_read_humidity(dev); /* read temperature 采集温度 */ temperature = aht10_read_temperature(dev); 3.2 ESP8266 3.2.1 底层uart简介 UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。\nUART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。\n串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。 异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。 数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。 空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。\n起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。\n数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。\n3.2.2 MQTT通讯协议介绍 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的\u0026quot;轻量级\u0026quot;通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。\n其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。\n实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。\n3.2.3 AT组件 AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:\n由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。\n3.2.4 MQTT协议及AT组件在RT-Thread中的使用 RT-Thread Settings设置\n添加AT Device及OneNET软件包\nAT Device配置:\nOneNET配置:\n首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。\n然后将创建的信息填写到settings中\n在组件中使能AT命令\n接线示意:\n引脚功能 引脚接线 TX P100 RX P101 VCC 5V GND GND FSP配置\n由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置\n首先点击RA Smart Configurator,记住这里使用的FSP版本为v3.5.0\n完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现#include \u0026lt;dfs_posix.h\u0026gt;未参与编译以及还有其他一些问题,可以参考这一issue[CPK-RA6M4] onenet上云报错\u0026lt;RT-Thread 的版本为 4.1.0 及以上\u0026gt;\n现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。\n然后就是数据上云,代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 if (onenet_mqtt_upload_digit(\u0026#34;temperature\u0026#34;,temperature) \u0026lt; 0) { LOG_E(\u0026#34;upload has an error, stop uploading\u0026#34;); } else { rt_kprintf(\u0026#34;humidity : %d.%d\\n\u0026#34;, (int)temperature, (int)(temperature * 10) % 10); } rt_thread_delay(5000); if (onenet_mqtt_upload_digit(\u0026#34;humidity\u0026#34;,humidity ) \u0026lt; 0) { LOG_E(\u0026#34;upload has an error, stop uploading\u0026#34;); } else { rt_kprintf(\u0026#34;humidity : %d.%d\\n\u0026#34;, (int)humidity, (int)(humidity * 10) % 10); } 这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。\n3.3 RC522 3.3.1 底层SPI协议简介 SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:\nMOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。 MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。 SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。 CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。 整体的传输大概可以分为以下几个过程:\n(1)主机先将NSS信号拉低,这样保证开始接收数据;\n(2)当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit;由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度。\n(3)主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;\n(4)主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;\n3.3.2 RC522读卡机制说明 首先来看下RC522与M1卡的通讯流程:\n寻卡-\u0026gt;防止卡片冲撞-\u0026gt;选卡-\u0026gt;休眠-\u0026gt;发送0x40(7bit)-\u0026gt;发送0x43-\u0026gt;发送0xa0等4字节-\u0026gt;发送0x00等18字节\n复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。\n防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。\n选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。\n三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。\n对数据块的操作: 读(Read):读一个块的数据; 写(Write):在一个块中写数据; 加(Increment):对数据块中的数值进行加值; 减(Decrement):对数据块中的数值进行减值; 传输(Transfer):将数据寄存器中的内容写入数据块中; 中止(Halt):暂停卡片的工作;\n3.3.3 RC522在RT-Thread的使用 首先打开settings,添加RC522软件包,并在硬件部分使能SPI1\n打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:\n引脚接线:\n引脚功能 引脚接线 MOSI P411 MISO P410 SCL P412 SDA P311 RST P312 VCC 3.3V GND GND IRQ 悬空 代码部分参考RC522sample\nSPI初始化配置:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include \u0026#34;mfrc522.h\u0026#34; static struct rt_spi_device mfrc522_spi_dev; struct rt_hw_spi_cs { rt_uint32_t pin; }; static struct rt_hw_spi_cs spi_cs; static int rt_hw_spi_rc522_init() { rt_err_t res = RT_EOK; // Attach Device spi_cs.pin = MFRC522_SS_PIN; rt_pin_mode(spi_cs.pin, PIN_MODE_OUTPUT); res = rt_spi_bus_attach_device(\u0026amp;mfrc522_spi_dev, MFRC522_SPI_DEVICE_NAME, MFRC522_SPI_BUS_NAME, (void*)\u0026amp;spi_cs); if (res != RT_EOK) { rt_kprintf(\u0026#34;[RC522] Failed to attach device %s\\n\u0026#34;, MFRC522_SPI_DEVICE_NAME); return res; } // Set device SPI Mode struct rt_spi_configuration cfg = {0}; cfg.data_width = 8; cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS; cfg.max_hz = MFRC522_SPICLOCK; rt_spi_configure(\u0026amp;mfrc522_spi_dev, \u0026amp;cfg); return RT_EOK; } /* 导出到自动初始化 */ INIT_COMPONENT_EXPORT(rt_hw_spi_rc522_init); 另外需要在完成一下配置,双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚\n打开mfrc522.c,修改配置MFRC522_SS_PIN及MFRC522_RST_PIN\n打开rtconfig.h,找到以下两个引脚的定义,修改成如下:\n注意:一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置\n1 2 #define MFRC522_SS_PIN 0x3b #define MFRC522_RST_PIN 0x3c 至此,RC522的相关配置结束\n3.4 SSD1306 3.4.1 底层I2C通信协议 (这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)\n3.4.2 SSD1306在RT-Thred的使用 接线示意:\n引脚功能 引脚接线 SCL P400 SDA P401 VCC 3.3V GND GND RT-Thread Settings配置:\n添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0\n打开rtconfig.h,添加i2c代码,注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码:\n1 2 3 4 #define BSP_USING_I2C #define BSP_USING_I2C0 #define BSP_I2C0_SCL_PIN 0x400 #define BSP_I2C0_SDA_PIN 0x401 打开drv_soft_i2c.c文件,添加代码:\n1 2 3 4 5 6 7 8 #ifdef BSP_USING_I2C0 #define I2C0_BUS_CONFIG \\ { \\ .scl = BSP_I2C0_SCL_PIN, \\ .sda = BSP_I2C0_SDA_PIN, \\ .bus_name = \u0026#34;i2c0\u0026#34;, \\ } #endif 打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:\n生成配置之后添加用户代码:\n1 2 3 4 5 6 7 8 9 10 11 12 #include \u0026#34;ssd1306.h\u0026#34; void oled_init() { ssd1306_Init(); ssd1306_Fill(Black); ssd1306_SetCursor(10, 25); ssd1306_WriteString(\u0026#34;Hello RT-Thread!\u0026#34;, Font_7x10, White); ssd1306_UpdateScreen(); } INIT_APP_EXPORT(oled_init); 实时时钟显示代码:\n1 2 3 4 5 6 7 8 9 10 ssd1306_Fill(White); ssd1306_SetCursor(0, 5); ssd1306_WriteString(\u0026#34;Now Time\u0026#34;, Font_16x26, Black); ssd1306_SetCursor(40, 40); ssd1306_WriteString(mstr, Font_11x18, Black); ssd1306_SetCursor(50, 40); ssd1306_WriteString(\u0026#34;:\u0026#34;, Font_11x18, Black); ssd1306_SetCursor(60, 40); ssd1306_WriteString(hstr, Font_11x18, Black); ssd1306_UpdateScreen(); 温湿度数据显示代码:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ssd1306_Fill(White); ssd1306_SetCursor(4, 2); ssd1306_WriteString(\u0026#34;Humi_Temp_Detection!\u0026#34;, Font_7x10, Black); ssd1306_UpdateScreen(); rt_thread_mdelay(1000); char buff[64]; snprintf(buff, sizeof(buff), \u0026#34;Temperature: %d.%d\\n\u0026#34;, (int)temperature, (int)(temperature * 10) % 10); ssd1306_SetCursor(15, 30); ssd1306_WriteString(buff, Font_6x8, Black); ssd1306_UpdateScreen(); rt_kprintf(\u0026#34;Temperature_OLED : %d.%d\\n\u0026#34;, (int)temperature, (int)(temperature * 10) % 10); snprintf(buff, sizeof(buff), \u0026#34;Humidity:%d.%d\\n\u0026#34;, (int)humidity, (int)(humidity * 10) % 10); ssd1306_SetCursor(25, 47); ssd1306_WriteString(buff, Font_6x8, Black); ssd1306_UpdateScreen(); rt_kprintf(\u0026#34;Humidity_OLED : %d.%d\\n\u0026#34;, (int)humidity, (int)(humidity * 10) % 10); 4、整体代码框架 4.1 多线程任务分配 本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。\n所以共创建四个线程:\n(1)RC522_thread:用于RC522读卡\n(2)aht10_read_thread:用于aht10读取温湿度数值\n(3)onenet_aht10_thread:云端数据上报\n(4)oled_thread:OLED显示\n4.2 线程间交互 本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。\n4.3 代码整合 在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。\n都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。\n5、踩坑指南 其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:\n(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为v3.5.0\n(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。\n(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。\n","date":"2022-07-24T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/","title":"CPK-RA6M4智慧门禁系统教学"},{"content":"1.安装ecilpse (1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包: 1 2 3 4 eclipse-kepler-for-arm-windows-x86_32.7z eclipse-kepler-for-arm-windows-x86_64.7z eclipse-kepler-for-arm-gtk-linux-x86_64.7z eclipse-kepler-for-arm-gtk-linux-x86_32.7z 选择自己需求对应的安装包下载解压即可(此处可点击下载)\n(2)配置好eclipse的环境变量 借鉴Eclipse环境变量配置-超详细\n2.开始工程的创建 (1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace) (2)建一个流水灯工程 首先在Project Explorer的空白栏右键单击-\u0026gt;New-\u0026gt;C Project 项目名称填写LED_test 点击next,finish\n找到我们的项目工程示例,将全部文件复制到剪贴板 工程右键选择paste,选择粘贴全部 这是粘贴好的文件项目 工程右键Build Project或直接CTRL+B编译 此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 进入该目录下,可以发现生成了led.bin映像文件 3.下载源码到SD卡 打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 4.实例演示 (1)清除开发板中的bootloader 由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴【Linux系统开发】Study210开发板刷安卓系统)\n(2)通过SD卡运行裸机程序 将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 ","date":"2022-07-24T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/","title":"Study210利用SD运行流水灯程序"},{"content":"一、破坏BootLoader 1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)\n2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)\n3.输入root(password:123456)\n4.然后输入busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync\n5.回车后显示\n1 2 1+0 records in 1+O records out 6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 此时重新启动开发板就无法启动了\n二、SD卡刷机(烧录uboot到SD卡中) 1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。\n此处如果SD烧写不成功,可尝试用管理员身份运行。 插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.\n2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)\n三、fastboot 下载安装镜像 1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。\n2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。\n3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android\nfastboot目录下应该包含的文件\nAndroid中应该包含的文件(由于这里我烧写的是安卓系统)\n4.进行内核和系统的烧写 ,具体代码如下:\n同时在SecureCRT下可以看到下载结果\n5.最后在windows控制台下输入 fastboot reboot命令重启系统即可。\n四、dnw 刷机(用fastboot刷Android ) 准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。 注意:\n(1)安装SecBulk.sys Njsmodi 2416 dnw drive的驱动程序在\\X210V3S_A\\tools\\USB驱动\\dnw_driver下,安装驱动需要禁用数字签名(可参考win10如何永久关闭数字签名)\n(2)在使用dnw过程中需要长按电源键,否则会断开连接。\n刷机步骤:\n1.将拨码开关拨到USB启动位置。\n2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin\n3.(同上操作)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin\n注意!!!:下载的同时要看SecureCRT界面,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。\n4.回到secureCRT\n1 2 输入fdisk -c 0 (进行分区) 输入fastboot (查看分区) 5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:\n最后再输入\n1 fastboot -w 全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。\n此文章参考于S5PV210 Study210开发板刷系统\n","date":"2022-07-23T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/","title":"Study210开发板刷安卓系统"},{"content":"《玩转RT-Thread》自制网络时钟 @[toc]\n一、准备工作 开发平台:RT-Thread Studio\n开发板:ART-PI\n主控芯片:STM32H750\n温湿度传感器:SHT30\n显示模组:0.96’OLED(SSD1306)\n串口调试助手:SecureCRT\n注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。\n二、新建RT-Thread 项目 三、获取温湿度数据 1、双击打开左边导航栏的RT-Thread Setting 2、使能软件模拟i2c(单击点亮即可) 3、配置i2c及相关引脚 这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置\n4、添加SHT3X软件包 CTRL+S保存配置,点击编译并下载\n具体RT-Thread Studio的一般使用可参照【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)\n此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功\n此时在串口输入help,可以看出有一个sht3x配置\n1 2 3 输入: sht3x probe i2c3 pd sht3x read(读取温湿度信息) 四、获取NTP时间 1、使能选择WiFi框架 2、使能AP6212库 3、添加easyflash和netutils软件包 鼠标右键netutils打开配置项\n使能NTP (网络时间协议)客户端\t使能软件模拟RTC\nCTRL+S保存配置\n修改配置\n1 2 3 4 (1)打开电脑中项目所在的路径-workpace-项目名称-packages-EasyFlash-v4.1.0-port,将port目录下的ef_fal_port.c文件复制到workpace-项目名称-board-port中 (2)修改port中宏定义FAL_EF_PART_NAME 中的名字 #define FAL_EF_PART_NAME \u0026#34;easyflash\u0026#34; //修改后的宏定义 此时再编译并下载到开发板中\n4、连接WiFi 1 2 3 4 5 wifi scan //搜索wifi wifi join [SSID] [PASSWORD] //连接WiFi SSID:WiFi名称 PASSWORD:WiFi密码 5、设置开机自连接WiFi (1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-09 ASUS the first version */ #include \u0026lt;rtthread.h\u0026gt; #ifdef BSP_USING_WIFI #include \u0026lt;wlan_mgnt.h\u0026gt; #include \u0026lt;wlan_cfg.h\u0026gt; #include \u0026lt;wlan_prot.h\u0026gt; #include \u0026lt;easyflash.h\u0026gt; #include \u0026lt;fal.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #if (EF_SW_VERSION_NUM \u0026lt; 0x40000) static char *str_base64_encode_len(const void *src, char *out, int input_length); static int str_base64_decode(const char *data, int input_length, char *decoded_data); static const unsigned char base64_table[65] = \u0026#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\u0026#34;; static const char base64_decode_table[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static char *str_base64_encode_len(const void *src, char *out, int len) { unsigned char *pos; const unsigned char *end, *in; size_t olen; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ olen += olen / 72; /* line feeds */ olen++; /* nul termination */ end = (const unsigned char *)src + len; in = (const unsigned char *)src; pos = (unsigned char *)out; while (end - in \u0026gt;= 3) { *pos++ = base64_table[in[0] \u0026gt;\u0026gt; 2]; *pos++ = base64_table[((in[0] \u0026amp; 0x03) \u0026lt;\u0026lt; 4) | (in[1] \u0026gt;\u0026gt; 4)]; *pos++ = base64_table[((in[1] \u0026amp; 0x0f) \u0026lt;\u0026lt; 2) | (in[2] \u0026gt;\u0026gt; 6)]; *pos++ = base64_table[in[2] \u0026amp; 0x3f]; in += 3; } if (end - in) { *pos++ = base64_table[in[0] \u0026gt;\u0026gt; 2]; if (end - in == 1) { *pos++ = base64_table[(in[0] \u0026amp; 0x03) \u0026lt;\u0026lt; 4]; *pos++ = \u0026#39;=\u0026#39;; } else { *pos++ = base64_table[((in[0] \u0026amp; 0x03) \u0026lt;\u0026lt; 4) | (in[1] \u0026gt;\u0026gt; 4)]; *pos++ = base64_table[(in[1] \u0026amp; 0x0f) \u0026lt;\u0026lt; 2]; } *pos++ = \u0026#39;=\u0026#39;; } *pos = \u0026#39;\\0\u0026#39;; return (char *)out; } /* * return: length, 0 is error. */ static int str_base64_decode(const char *data, int input_length, char *decoded_data) { int out_len; int i, j; if (input_length % 4 != 0) return 0; out_len = input_length / 4 * 3; if (data[input_length - 1] == \u0026#39;=\u0026#39;) out_len--; if (data[input_length - 2] == \u0026#39;=\u0026#39;) out_len--; for (i = 0, j = 0; i \u0026lt; input_length;) { uint32_t sextet_a = data[i] == \u0026#39;=\u0026#39; ? 0 \u0026amp; i++ : base64_decode_table[data[i++]]; uint32_t sextet_b = data[i] == \u0026#39;=\u0026#39; ? 0 \u0026amp; i++ : base64_decode_table[data[i++]]; uint32_t sextet_c = data[i] == \u0026#39;=\u0026#39; ? 0 \u0026amp; i++ : base64_decode_table[data[i++]]; uint32_t sextet_d = data[i] == \u0026#39;=\u0026#39; ? 0 \u0026amp; i++ : base64_decode_table[data[i++]]; uint32_t triple = (sextet_a \u0026lt;\u0026lt; 3 * 6) + (sextet_b \u0026lt;\u0026lt; 2 * 6) + (sextet_c \u0026lt;\u0026lt; 1 * 6) + (sextet_d \u0026lt;\u0026lt; 0 * 6); if (j \u0026lt; out_len) decoded_data[j++] = (triple \u0026gt;\u0026gt; 2 * 8) \u0026amp; 0xFF; if (j \u0026lt; out_len) decoded_data[j++] = (triple \u0026gt;\u0026gt; 1 * 8) \u0026amp; 0xFF; if (j \u0026lt; out_len) decoded_data[j++] = (triple \u0026gt;\u0026gt; 0 * 8) \u0026amp; 0xFF; } return out_len; } static int read_cfg(void *buff, int len) { char *wlan_cfg_info = RT_NULL; wlan_cfg_info = ef_get_env(\u0026#34;wlan_cfg_info\u0026#34;); if (wlan_cfg_info != RT_NULL) { str_base64_decode(wlan_cfg_info, rt_strlen(wlan_cfg_info), buff); return len; } else { return 0; } } static int get_len(void) { int len; char *wlan_cfg_len = RT_NULL; wlan_cfg_len = ef_get_env(\u0026#34;wlan_cfg_len\u0026#34;); if (wlan_cfg_len == RT_NULL) { len = 0; } else { len = atoi(wlan_cfg_len); } return len; } static int write_cfg(void *buff, int len) { char wlan_cfg_len[12] = {0}; char *base64_buf = RT_NULL; base64_buf = rt_malloc(len * 4 / 3 + 4); /* 3-byte blocks to 4-byte, and the end. */ if (base64_buf == RT_NULL) { return -RT_ENOMEM; } rt_memset(base64_buf, 0, len); /* interger to string */ sprintf(wlan_cfg_len, \u0026#34;%d\u0026#34;, len); /* set and store the wlan config lengths to Env */ ef_set_env(\u0026#34;wlan_cfg_len\u0026#34;, wlan_cfg_len); str_base64_encode_len(buff, base64_buf, len); /* set and store the wlan config information to Env */ ef_set_env(\u0026#34;wlan_cfg_info\u0026#34;, base64_buf); ef_save_env(); rt_free(base64_buf); return len; } #else static int read_cfg(void *buff, int len) { size_t saved_len; ef_get_env_blob(\u0026#34;wlan_cfg_info\u0026#34;, buff, len, \u0026amp;saved_len); if (saved_len == 0) { return 0; } return len; } static int get_len(void) { int len; size_t saved_len; ef_get_env_blob(\u0026#34;wlan_cfg_len\u0026#34;, \u0026amp;len, sizeof(len), \u0026amp;saved_len); if (saved_len == 0) { return 0; } return len; } static int write_cfg(void *buff, int len) { /* set and store the wlan config lengths to Env */ ef_set_env_blob(\u0026#34;wlan_cfg_len\u0026#34;, \u0026amp;len, sizeof(len)); /* set and store the wlan config information to Env */ ef_set_env_blob(\u0026#34;wlan_cfg_info\u0026#34;, buff, len); return len; } #endif /* (EF_SW_VERSION_NUM \u0026lt; 0x40000) */ static const struct rt_wlan_cfg_ops ops = { read_cfg, get_len, write_cfg }; void wlan_autoconnect_init(void) { fal_init(); easyflash_init(); rt_wlan_cfg_set_ops(\u0026amp;ops); rt_wlan_cfg_cache_refresh(); } #endif (2)在main.c中添加自动连接函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026#34;drv_common.h\u0026#34; #define LED_PIN GET_PIN(I, 8) extern void wlan_autoconnect_init(void); int main(void) { rt_uint32_t count = 1; rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); /* init Wi-Fi auto connect feature */ wlan_autoconnect_init(); /* enable auto reconnect on WLAN device */ rt_wlan_config_autoreconnect(RT_TRUE); return RT_EOK; } #include \u0026#34;stm32h7xx.h\u0026#34; static int vtor_config(void) { /* Vector Table Relocation in Internal QSPI_FLASH */ SCB-\u0026gt;VTOR = QSPI_BASE; return 0; } INIT_BOARD_EXPORT(vtor_config); 编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。\n五、OLED屏显示温湿度和实时时间信息 1、添加u8g2软件包 2、编写oled_display显示线程 (1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。\n代码如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 #include \u0026lt;rthw.h\u0026gt; #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026lt;U8g2lib.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;board.h\u0026gt;\t#include \u0026#34;drv_common.h\u0026#34; #include \u0026lt;drv_soft_i2c.h\u0026gt; extern \u0026#34;C\u0026#34; { #include \u0026lt;sht3x.h\u0026gt; } extern \u0026#34;C\u0026#34; { sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr); rt_err_t sht3x_read_singleshot(sht3x_device_t dev); } #define OLED_I2C_PIN_SCL 24 // #define OLED_I2C_PIN_SDA 25 // static U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,\\ /* clock=*/ OLED_I2C_PIN_SCL,\\ /* data=*/ OLED_I2C_PIN_SDA,\\ /* reset=*/ U8X8_PIN_NONE); #define SUN 0 #define SUN_CLOUD 1 #define CLOUD 2 #define RAIN 3 #define THUNDER 4 static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol) { // fonts used: // u8g2_font_open_iconic_embedded_6x_t // u8g2_font_open_iconic_weather_6x_t // encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic switch(symbol) { case SUN: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 69); break; case SUN_CLOUD: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 65); break; case CLOUD: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 64); break; case RAIN: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 67); break; case THUNDER: u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t); u8g2.drawGlyph(x, y, 67); break; } } static void drawWeather(uint8_t symbol, int degree) { drawWeatherSymbol(0, 63, symbol); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(55, 63); u8g2.print(degree); u8g2.print(\u0026#34;C\u0026#34;); } static void drawHumidity(uint8_t symbol, int humidity) { drawWeatherSymbol(0, 63, symbol); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(55, 63); u8g2.print(humidity); u8g2.print(\u0026#34;%\u0026#34;); } #ifdef __cplusplus extern \u0026#34;C\u0026#34; { #endif void oled_display() { u8g2.begin(); u8g2.clearBuffer(); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(48+3, 42); u8g2.print(\u0026#34;Hi~\u0026#34;); // requires enableUTF8Print() u8g2.setFont(u8g2_font_6x13_tr); // choose a suitable font u8g2.drawStr(30, 60, \u0026#34;By Mculover666\u0026#34;); // write something to the internal memory u8g2.sendBuffer(); sht3x_device_t sht3x_device; sht3x_device = sht3x_init(\u0026#34;i2c3\u0026#34;, 0x44); rt_thread_mdelay(2000); int status = 0; char mstr[3]; char hstr[3]; time_t now; struct tm *p; int min = 0, hour = 0; int temperature = 0,humidity = 0; while(1) { switch(status) { case 0: now = time(RT_NULL); p=gmtime((const time_t*) \u0026amp;now); hour = p-\u0026gt;tm_hour; min = p-\u0026gt;tm_min; sprintf(mstr, \u0026#34;%02d\u0026#34;, min); sprintf(hstr, \u0026#34;%02d\u0026#34;, hour); u8g2.firstPage(); do { u8g2.setFont(u8g2_font_logisoso42_tn); u8g2.drawStr(0,63,hstr); u8g2.drawStr(50,63,\u0026#34;:\u0026#34;); u8g2.drawStr(67,63,mstr); } while ( u8g2.nextPage() ); rt_thread_mdelay(5000); status = 1; break; case 1: if(RT_EOK == sht3x_read_singleshot(sht3x_device)) { temperature = (int)sht3x_device-\u0026gt;temperature; } else { temperature = 0; } u8g2.clearBuffer(); drawWeather(SUN, temperature); u8g2.sendBuffer(); rt_thread_mdelay(5000); status = 2; break; case 2: if(RT_EOK == sht3x_read_singleshot(sht3x_device)) { humidity = (int)sht3x_device-\u0026gt;humidity; } else { humidity = 0; } u8g2.clearBuffer(); drawHumidity(RAIN, humidity); u8g2.sendBuffer(); rt_thread_mdelay(5000); status = 0; break; } } } MSH_CMD_EXPORT(oled_display, oled start); #ifdef __cplusplus } #endif (2)在 applications 文件夹下创建oled_display.h\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-09 ASUS the first version */ #ifndef APPLICATIONS_OLED_DISPLAY_H_ #define APPLICATIONS_OLED_DISPLAY_H_ #ifdef __cplusplus extern \u0026#34;C\u0026#34; { #endif void oled_display(void); #ifdef __cplusplus } #endif #endif /* APPLICATIONS_OLED_DISPLAY_H_ */ (3)最终的主函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 /* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-09-02 RT-Thread first version */ #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026#34;drv_common.h\u0026#34; extern void wlan_autoconnect_init(void); int main(void) { rt_uint32_t count = 1; rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); wlan_autoconnect_init(); rt_wlan_config_autoreconnect(RT_TRUE); oled_display(); return RT_EOK; } #include \u0026#34;stm32h7xx.h\u0026#34; static int vtor_config(void) { /* Vector Table Relocation in Internal QSPI_FLASH */ SCB-\u0026gt;VTOR = QSPI_BASE; return 0; } INIT_BOARD_EXPORT(vtor_config); (4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。\n1 2 3 4 5 6 7 8 9 10 11 12 13 /*-------------------------- I2C CONFIG BEGIN --------------------------*/ #ifdef BSP_USING_I2C1 #define BSP_I2C1_SCL_PIN 24 // p2 10 PB8 #define BSP_I2C1_SDA_PIN 25 // p2 7 PB9 #endif #ifdef BSP_USING_I2C3 #define BSP_I2C3_SCL_PIN 119 //p1 29 PH7 #define BSP_I2C3_SDA_PIN 120 //p1 28 PH8 #endif /*-------------------------- UART CONFIG END --------------------------*/ 六、实验展示 七、问题总结 注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装\n1 2 3 4 5 6 7 8 9 10 11 12 //如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 #ifdef __cplusplus extern \u0026#34;C\u0026#34; { #endif // cpp函数 #ifdef __cplusplus } #endif 在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。\n这次的分享就到这里,有相关问题的欢迎留言私信!\n","date":"2022-07-22T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/","title":"ART-Pi 网络时钟"},{"content":"ubuntu终端下命令ifconfig的问题解决 问题一. ifconfig之后只显示lo,没有看到eth0 问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。\n问题一:ifconfig之后只显示lo,没有看到eth0 ? 1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback 这边的设置是本地回路。在后面加上\n1 2 3 4 iface eth0 inet static address 192.168.1.230 //(ip地址) netmask 255.255.255.0 //(子网掩码) gateway 192.168.1.1 //(网关) 其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。\n2.eth0被关了 输入命令行:ifconfig eth0 up #开启eth0\n问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”? 1.先用sudo dhclient eth0更新IP地址 2.然后运行sudo ifconfig eth0 3.reboot\n问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。 设置好后,如果直接ping www.baidu.com会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。\nnameserver 8.8.8.8 nameserver 8.8.4.4 这两个是Google提供的免费DNS服务器的IP地址\n","date":"2022-07-22T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/","title":"ifconfig不显示ip地址"},{"content":"内核编译常用命令 安装模块 lsmod module_test.ko 创建设备文件 mknod /dev/test c 250 0 查看设备状态 lsmod module_test.ko 查看设备注册信息(分为字符设备和块设备) cat /proc/devices\n知识补充: 1 2 3 4 5 6 7 8 9 10 #include\u0026lt;stdio.h\u0026gt; int main(void) { int i; static int j; printf(i); printf(j); } // 注意:这里如果没有指定i值,则打印出来的是随机值 // 如果定义一个静态变量而没有赋值,则打印默认为0 虚拟驱动创建流程 首先进入x210_bsp/kernel\nmake menuconfig\nmake -j4\ncp arch/arm/boot/zImage /tftpboot/ -f\n重启开发板查看开发板设备\nls /sys/devices/platform/\ncd sys/class/leds\nled_test_4编写完成后\n编译不报错即可\ncd /root/x210_bsp/kernel/drivers/leds/\ncp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./\nvi Makefile-\u0026gt;\nobj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o\nvi Kconfig更改依赖(添加以下文件)\nconfig LEDS_S5PV210 tristate \u0026quot;LED Support for S5PV210\u0026quot; help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.\n进入到x210_bsp/kernel\n执行make menuconfig\n可以发现生成了新的配置(Device Drivers-\u0026gt; LED_Support),使能这个\n执行make编译\ncp arch/arm/boot/zImage /tftpboot/ -f\nsecureCRT:\ncd sys/class/leds\n进入LED1,执行\necho 1 \u0026gt; brightness // 灯亮\necho 0 \u0026gt; brightness //灯灭\n最后附上源代码:\nleds-s5pv210.c\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 #include \u0026lt;linux/module.h\u0026gt; #include \u0026lt;linux/init.h\u0026gt; #include \u0026lt;linux/fs.h\u0026gt; #include \u0026lt;asm/uaccess.h\u0026gt; #include \u0026lt;mach/gpio-bank.h\u0026gt; #include \u0026lt;mach/regs-gpio.h\u0026gt; #include \u0026lt;linux/ioport.h\u0026gt; #include \u0026lt;asm/io.h\u0026gt; #include \u0026lt;linux/cdev.h\u0026gt; #include \u0026lt;linux/device.h\u0026gt; #include \u0026lt;mach/gpio.h\u0026gt; #include \u0026lt;linux/leds.h\u0026gt; #define GPIO_LED1\tS5PV210_GPJ0(3) #define GPIO_LED2\tS5PV210_GPJ0(4) #define GPIO_LED3\tS5PV210_GPJ0(5) #define X210_LED_OFF\t1 #define X210_LED_ON\t0 struct led_classdev mydev1; struct led_classdev mydev2; struct led_classdev mydev3; void s5pv210_led1_set(struct led_classdev *led_cdev,enum led_brightness value) { printk(KERN_INFO \u0026#34;s5pv210_led1_set\\n\u0026#34;); if(value == LED_OFF) { gpio_set_value(GPIO_LED1,X210_LED_OFF); } else { gpio_set_value(GPIO_LED1,X210_LED_ON); } } void s5pv210_led2_set(struct led_classdev *led_cdev,enum led_brightness value) { printk(KERN_INFO \u0026#34;s5pv210_led2_set\\n\u0026#34;); if(value == LED_OFF) { gpio_set_value(GPIO_LED2,X210_LED_OFF); } else { gpio_set_value(GPIO_LED2,X210_LED_ON); } } void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness value) { printk(KERN_INFO \u0026#34;s5pv210_led3_set\\n\u0026#34;); if(value == LED_OFF) { gpio_set_value(GPIO_LED3,X210_LED_OFF); } else { gpio_set_value(GPIO_LED3,X210_LED_ON); } } static int __init s5pv210_led_init(void) { int ret = -1; // 申请GPIO if(gpio_request(GPIO_LED1,\u0026#34;led1_gpj0.3\u0026#34;)) { printk(KERN_ERR \u0026#34;gpio_request failed.\\n\u0026#34;); } else { gpio_direction_output(GPIO_LED1,1); } mydev1.name = \u0026#34;led1\u0026#34;; mydev1.brightness = 0; mydev1.brightness_set = s5pv210_led1_set; ret = led_classdev_register(NULL,\u0026amp;mydev1); if(ret \u0026lt; 0) { printk(KERN_ERR \u0026#34;led_classdev_register failed.\\n\u0026#34;); return ret; } mydev2.name = \u0026#34;led2\u0026#34;; mydev2.brightness = 0; mydev2.brightness_set = s5pv210_led2_set; ret = led_classdev_register(NULL,\u0026amp;mydev2); if(ret \u0026lt; 0) { printk(KERN_ERR \u0026#34;led_classdev_register failed.\\n\u0026#34;); return ret; } mydev3.name = \u0026#34;led3\u0026#34;; mydev3.brightness = 0; mydev3.brightness_set = s5pv210_led3_set; ret = led_classdev_register(NULL,\u0026amp;mydev3); if(ret \u0026lt; 0) { printk(KERN_ERR \u0026#34;led_classdev_register failed.\\n\u0026#34;); return ret; } return 0; } static void __exit s5pv210_led_exit(void) { led_classdev_unregister(\u0026amp;mydev1); led_classdev_unregister(\u0026amp;mydev2); led_classdev_unregister(\u0026amp;mydev3); gpio_free(GPIO_LED1); gpio_free(GPIO_LED2); gpio_free(GPIO_LED3); } module_init(s5pv210_led_init); module_exit(s5pv210_led_exit); MODULE_LICENSE(\u0026#34;GPL\u0026#34;); MODULE_AUTHOR(\u0026#34;WYQ\u0026#34;); MODULE_DESCRIPTION(\u0026#34;module_test\u0026#34;); Makefile\n1 2 3 4 5 6 7 8 9 10 11 12 13 #KERN_VER = $(shell uname -r) #KERN_DIR = /lib/modules/$(KERN_VER)/build KERN_DIR = /root/x210_bsp/kernel obj-m += leds-s5pv210.o all: make -C $(KERN_DIR) M=`pwd` modules .PHONY:clean clean: make -C $(KERN_DIR) M=`pwd` modules clean ","date":"2022-07-22T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/","title":"x210开发板 虚拟驱动创建流程"},{"content":"一、概述: 多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:\n信号量(semaphore)、互斥量(mutex)、和事件集(event)\n二、信号量 1、简述 信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。\n信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例(资源)。\n2、信号量结构体 1 2 3 4 5 6 7 struct rt_semaphore { struct rt_ipc_object parent; /**\u0026lt; 继承自ipc_object类 */ rt_uint16_t value; /**\u0026lt; value of semaphore. */ rt_uint16_t reserved; /**\u0026lt; reserved field 预留*/ }; 当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。\n3、信号量使用及管理 对一个信号量的操作包含:创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量。\n1)动态创建信号量\n当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。\n当选择 RT_IPC_FLAG_FIFO(先进先出)方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; 当选择 RT_IPC_FLAG_PRIO(优先级等待)方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。\n函数声明:\nrt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);\n参数介绍:\n注意:\n(1)此处的*name定义最多只能显示八个字符\n(2)查看rt_sem_create()函数返回值是--\u0026gt;typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore 1 2 3 4 // flag值\t如下 #define RT_IPC_FLAG_FIFO 0x00 /**\u0026lt; FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */ #define RT_IPC_FLAG_PRIO 0x01 /**\u0026lt; PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */ 2)动态创建的信号量删除\n系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。\n调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。\n函数声明 rt_err_t rt_sem_delete(rt_sem_t sem);\n实例\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026lt;board.h\u0026gt; #include \u0026lt;rtdbg.h\u0026gt; rt_sem_t sem1; int main(void) { sem1 = rt_sem_create(\u0026#34;sem_1\u0026#34;,1,RT_IPC_FLAG_FIFO); if(sem1 == RT_NULL) { LOG_E(\u0026#34;rt_sem_create is failure...\\n\u0026#34;); } LOG_D(\u0026#34;rt_sem_create is success...\\n\u0026#34;); return 0; } 3)静态创建信号量\n描述\n对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。\n函数声明\n1 2 3 4 rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag); 参数描述\n4)脱离信号量\n描述\n脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于静态初始化的信号量。\n函数声明\n1 rt_err_t rt_sem_detach(rt_sem_t sem); 5)获取信号量\n描述\n线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。\n如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。\n如果在参数 time 指定的时间内依然得不到信号量,线程将超时返回,返回值是 - RT_ETIMEOUT。\n函数声明\n1 rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time); 参数描述\n1 2 3 4 // time参数 #define RT_WAITING_FOREVER -1 /**\u0026lt; Block forever until get resource. */ #define RT_WAITING_NO 0 /**\u0026lt; Non-block. */ 1 2 3 4 5 // 扩展: rt_err_t rt_sem_trytake(rt_sem_t sem); // 无等待获取信号量 // 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。 6)信号量释放\n函数声明\n1 rt_err_t rt_sem_release(rt_sem_t sem); 描述\n例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。\n4、信号量实例演示 这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态\n由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态\n查看信号量设定的标志位是RT_IPC_FLAG_FIFO,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1-\u0026gt;线程2-\u0026gt;线程1-\u0026gt;线程2\u0026hellip;的顺序执行的,这样就实现了线程的并发互斥运行。\n最后附上测试源代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026lt;board.h\u0026gt; #include \u0026lt;rtdbg.h\u0026gt; rt_sem_t sem1; struct rt_semaphore sem2; rt_thread_t th1,th2; int flags = 0; void th1_entry(void *parameter) { while(1) { rt_thread_mdelay(8000); rt_sem_take(sem1, RT_WAITING_FOREVER);// 获取信号量 flags++; if(flags == 100) flags = 0; rt_kprintf(\u0026#34;th1_entry [%d]\\n\u0026#34;,flags); rt_sem_release(\u0026amp;sem2);// 对获取的信号量进行释放 } } void th2_entry(void *parameter) { while(1) { rt_sem_take(\u0026amp;sem2, RT_WAITING_FOREVER);// 获取信号量 if(flags \u0026gt; 0) flags--; rt_kprintf(\u0026#34;th2_entry [%d]\\n\u0026#34;,flags); rt_sem_release(sem1);// 对获取的信号量进行释放 rt_thread_mdelay(1000); } } int main(void) { int ret = 0; sem1 = rt_sem_create(\u0026#34;sem_1\u0026#34;,1,RT_IPC_FLAG_FIFO); if(sem1 == RT_NULL) { LOG_E(\u0026#34;sem1 rt_sem_create is failure...\\n\u0026#34;); } LOG_D(\u0026#34;sem1 rt_sem_create is success...\\n\u0026#34;); ret = rt_sem_init(\u0026amp;sem2, \u0026#34;sem2\u0026#34;, 0, RT_IPC_FLAG_FIFO); if(ret \u0026lt; 0) { LOG_E(\u0026#34;sem2 rt_sem_create is failure...\\n\u0026#34;); return ret; } LOG_D(\u0026#34;sem2 rt_sem_init successed...\\n\u0026#34;); th1 = rt_thread_create(\u0026#34;th1\u0026#34;, th1_entry, NULL, 512, 20, 5); if(th1 == RT_NULL) { LOG_E(\u0026#34;th1 rt_thread_create failed...\\n\u0026#34;); return -ENOMEM; } LOG_D(\u0026#34;th1 rt_thread_create successed...\\n\u0026#34;); th2 = rt_thread_create(\u0026#34;th2\u0026#34;, th2_entry, NULL, 512, 20, 5); if(th2 == RT_NULL) { LOG_E(\u0026#34;th2 rt_thread_create failed...\\n\u0026#34;); return -ENOMEM; } LOG_D(\u0026#34;th2 rt_thread_create successed...\\n\u0026#34;); rt_thread_startup(th1); rt_thread_startup(th2); return 0; } ","date":"2022-07-17T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/","title":"线程间同步 信号量"},{"content":"以删除apache2为例,其它程序也都是这么删\u0026hellip;\n1.先通过apt删除程序和相关配置文件\n1 sudo apt-get --purge remove apache2 2.自动删除不使用的软件包\n1 sudo apt-get autoremove 3.找出与apache2相关的程序\n1 dpkg --get-selections|grep apache2 没有就不显示,如果有就删除这些相关的程序\n1 sudo apt-get --purge remove xxx 4.查看apache2是否还有进程存在\n1 ps -ef |grep apache2 如果有就杀掉\n1 sudo kill -9 8888 //后面接pid号码,用空格隔开 5.全局查找和apache2相关的文件,需要一定时间,稍等\n1 sudo find / -name apache2* 将找到的文件逐个删掉\n1 sudo rm -rf /usr/share/bash-completion/completions/apache2ctl 这样就彻底删除掉apache2了\n","date":"2022-07-16T00:00:00Z","image":"https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/","title":"ubuntu彻底删除通过apt方式安装的程序"},{"content":"原理实战请查看【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)\n一、序言 在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。\n下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:\n1.读取数据 2.显示数据\n简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 在RT-Thread 中,与上述子任务对应的程序实体就是线程,线程是实现任务的载体。 它是RT-Thread中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 上下文:当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。\n二、线程管理的功能特点 RT-Thread 线程管理的主要功能是对线程进行管理和调度,系统中总共存在两类线程,分别是系统线程和用户线程。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。\n如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。 当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。 当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(详细内容可参考【操作系统】进程上下文和线程上下文)信息恢复。 三、线程的工作机制 1.线程控制块 在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /* 线程控制块*/ struct rt_thread { /* rt 对象*/ char name[RT_NAME_MAX]; /* 线程名称*/ rt_uint8_t type; /* 对象类型*/ rt_uint8_t flags; /* 标志位*/ rt_list_t list; /* 对象列表*/ rt_list_t tlist; /* 线程列表*/ /* 栈指针与入口指针*/ void *sp; /* 栈指针*/ void *entry; /* 入口函数指针*/ void *parameter; /* 参数*/ void *stack_addr; /* 栈地址指针*/ rt_uint32_t stack_size; /* 栈大小*/ /* 错误代码*/ rt_err_t error; /* 线程错误代码*/ rt_uint8_t stat; /* 线程状态*/ /* 优先级*/ rt_uint8_t current_priority; /* 当前优先级*/ rt_uint8_t init_priority; /* 初始优先级*/ rt_uint32_t number_mask; ...... rt_ubase_t init_tick; /* 线程初始化计数值*/ rt_ubase_t remaining_tick; /* 线程剩余计数值*/ struct rt_timer thread_timer; /* 内置线程定时器*/ void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/ rt_uint32_t user_data; /* 用户数据*/ }; 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。 cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。 最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。 2.线程的重要属性 (1) 线程栈 RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。 线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。 对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。 线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 (2) 线程状态 线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:\n状态 描述 初始态 当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT 就绪态 在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY 运行态 线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING 挂起态 也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND 关闭态 当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE (3) 线程优先级 RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。\nRT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。\n(4) 时间片 每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。\n假设有2 个优先级相同的就绪态线程A 与B,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 (5) 线程的入口函数 线程控制块中的entry是线程的入口函数,它是线程实现预期功能的函数。\n线程的入口函数由用户设计实现,一般有以下两种代码形式: 1.无限循环模式\n在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 界事件的发生,而后进行相应的服务:\n1 2 3 4 5 6 7 8 void thread_entry(void* paramenter) { while (1) { /* 等待事件的发生*/ /* 对事件进行服务、进行处理*/ } } 作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 所以在实时操作系统中必须注意的一点就是:线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。\n2.顺序执行或有限次循环模式\n如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。\n1 2 3 4 5 6 7 8 static void thread_entry(void* parameter) { /* 处理事务#1 */ … /* 处理事务#2 */ … /* 处理事务#3 */ } (6) 常见的线程错误码 1 2 3 4 5 6 7 8 9 10 11 #define RT_EOK 0 /* 无错误*/ #define RT_ERROR 1 /* 普通错误*/ #define RT_ETIMEOUT 2 /* 超时错误*/ #define RT_EFULL 3 /* 资源已满*/ #define RT_EEMPTY 4 /* 无资源*/ #define RT_ENOMEM 5 /* 无内存*/ #define RT_ENOSYS 6 /* 系统不支持*/ #define RT_EBUSY 7 /* 系统忙*/ #define RT_EIO 8 /* IO 错误*/ #define RT_EINTR 9 /* 中断系统调用*/ #define RT_EINVAL 10 /* 非法参数*/ 3.线程状态切换 RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: 线程通过调用函数rt_thread_create/init() 进入到初始状态(RT_THREAD_INIT); 初始状态的线程通过调用函数rt_thread_startup() 进入到就绪状态(RT_THREAD_READY); 就绪状态的线程被调度器调度后进入运行状态(RT_THREAD_RUNNING); 当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态(RT_THREAD_SUSPEND); 处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。 挂起状态的线程,如果调用rt_thread_delete/detach() 函数,将更改为关闭状态(RT_THREAD_CLOSE); 而运行状态的线程,如果运行结束,就会在线程的最后部分执行rt_thread_exit() 函数,将状态更改为关闭状态。 !!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。\n4.系统线程 系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。\n(1)空闲线程 空闲线程是系统创建的最低优先级的线程,线程状态永远为就绪态。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。\n另外,空闲线程在RT-Thread 也有着它的特殊用途:\n若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。 空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于钩子函数和看门狗不懂的可以看这里) (2) 主线程 在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。\n过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 四、线程的管理方式 可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。\n动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。\n下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 1.创建和删除线程 (1)创建线程 一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:\n1 2 3 4 5 6 rt_thread_t rt_thread_create(const char* name, void (*entry)(void* parameter), void* parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。\n线程创建rt_thread_create() 的参数和返回值见下图: (2)删除线程 对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:\nrt_err_t rt_thread_delete(rt_thread_t thread); 调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。\n线程删除rt_thread_delete() 接口的参数和返回值见下图: 这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。\n2.初始化和脱离线程 (1)初始化线程 线程的初始化可以使用下面的函数接口完成,来初始化静态线程对象:\n1 2 3 4 5 rt_err_t rt_thread_init(struct rt_thread* thread, const char* name, void (*entry)(void* parameter), void* parameter, void* stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); (2)脱离线程 对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:\nrt_err_t rt_thread_detach (rt_thread_t thread); 参数 描述 thread 线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。 返回 \u0026mdash; RT_EOK 线程脱离成功 -RT_ERROR 线程脱离失败 3.启动线程 创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:\nrt_err_t rt_thread_startup(rt_thread_t thread); 当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 动的线程优先级比当前线程优先级高,将立刻切换到这个线程。\n4.获得当前线程 在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:\nrt_thread_t rt_thread_self(void); 5.使线程出让处理器资源 当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。\n线程让出处理器使用下面的函数接口:\nrt_err_t rt_thread_yield(void); 调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。\n6.使线程睡眠 在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。\n线程睡眠可使用以下三个函数接口:\n1 2 3 rt_err_t rt_thread_sleep(rt_tick_t tick); rt_err_t rt_thread_delay(rt_tick_t tick); rt_err_t rt_thread_mdelay(rt_int32_t ms); 7.挂起和恢复线程 (1)线程挂起 当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。 处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。 线程挂起使用下面的函数接口:\nrt_err_t rt_thread_suspend (rt_thread_t thread); !!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。\n(2)恢复线程 恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。\n线程恢复使用下面的函数接口:\nrt_err_t rt_thread_resume (rt_thread_t thread); 8.控制线程 当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:\nrt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); 指示控制命令cmd 当前支持的命令包括: •RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级; •RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用; •RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。 设置和删除空闲钩子 空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。\n设置/ 删除空闲钩子的接口如下:\nrt_err_t rt_thread_idle_sethook(void (*hook)(void)); rt_err_t rt_thread_idle_delhook(void (*hook)(void)); 参数 描述 hook 设置/删除的钩子函数 返回 \u0026mdash; RT-EOK 设置/删除成功 -RT_EFULL 设置失败 -RT_ENOSYS 删除失败 !!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。\n10.设置调度器钩子 在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。\n在系统线程切换时,这个钩子函数将被调用:\nvoid rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); 设置调度器钩子函数的输入参数如下表所示:\n参数 描述 hook 表示用户定义的钩子函数指针 钩子函数hook() 的声明如下:\nvoid hook(struct rt_thread* from, struct rt_thread* to); 参数 描述 from 表示系统所要切换出的线程控制块指针 to 表示系统所要切换到的线程控制块指针 !!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。\n资料参考: (1)【STM32】HAL库 STM32CubeMX教程五\u0026mdash;-看门狗(独立看门狗,窗口看门狗) (2)什么是钩子函数 (3)RT-Thread文档中心\n","date":"2022-07-16T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/","title":"线程管理"},{"content":"一、i2c协议 由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。\n二、i2c物理层 i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 SDA:用于传输数据 SCL:用于同步数据收发\n每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问\ni2c支持多主控,任何时间点都只能有一个主控。 i2c器件的SDA引脚和SCL引脚是开漏电路(参照资料)形式,因此,SDA和SCL总线都需要连接上拉电阻(参照资料),当总线空闲时,两条总线均为高电平。\n各器件的SDA和SCL信号线在总线上都是线与关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)\n三、i2c协议层 协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。\n1.i2c总线的位传输 数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 数据改变:当SCL为低电平时,SDA才可以改变电平 i2c位传输时序图 2.i2c总线的开始和结束信号 开始信号:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 结束信号:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。\n3.i2c应答信号 在主机发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答ACK(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平) 当从机接收不到数据或通信故障时,从机必须使SDA保持高电平,主机产生一个结束信号终止传输或者产生新的传输。 4.i2c总线的仲裁机制 SDA的仲裁也是建立在总线具有线与逻辑功能的原理上的。 节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。 SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线) 当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是线与连接。 四、访问i2c总线设备 一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:\n函数 描述 rt_device_find() 根据I2C 总线设备名称查找设备获取设备句柄 rt_i2c_transfer() 传输数据 五、查找i2c总线设备 在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,\nrt_device_t rt_device_find(const char* name); 参数 描述 name i2c总线设备名称 返回 \u0026ndash; 设备句柄 查找到对应设备将返回相应的设备句柄 RT-NULL 没有找到相应的设备对象 一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:\n1 2 3 4 #define AHT10_I2C_BUS_NAME \u0026#34;i2c1\u0026#34; /* 传感器连接的I2C总线设备名称*/ struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ /* 查找I2C总线设备, 获取I2C总线设备句柄*/ i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); 六、数据传输 获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:\n1 2 3 rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); 参数 描述 bus i2c总线设备句柄 msgs[] 待传输的消息数组指针 num 消息数组的元素个数 返回 - - - 消息数组的元素个数 成功 错误码 失败 和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。 参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 !!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。 I2C 消息数据结构原型如下:\n1 2 3 4 5 6 7 struct rt_i2c_msg { rt_uint16_t addr; /* 从机地址*/ rt_uint16_t flags; /* 读、写标志等*/ rt_uint16_t len; /* 读写数据字节数*/ rt_uint8_t *buf; /* 读写数据缓冲区指针 */ } 从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。 标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 !!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。 1 2 3 4 5 6 #define RT_I2C_WR 0x0000 /* 写标志*/ #define RT_I2C_RD (1u \u0026lt;\u0026lt; 0) /* 读标志*/ #define RT_I2C_ADDR_10BIT (1u \u0026lt;\u0026lt; 2) /* 10 位地址模式*/ #define RT_I2C_NO_START (1u \u0026lt;\u0026lt; 4) /* 无开始条件*/ #define RT_I2C_IGNORE_NACK (1u \u0026lt;\u0026lt; 5) /* 忽视NACK */ #define RT_I2C_NO_READ_ACK (1u \u0026lt;\u0026lt; 6) /* 读的时候不发送ACK */ 使用示例如下所示:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #define AHT10_I2C_BUS_NAME \u0026#34;i2c1\u0026#34; /* 传感器连接的I2C总线设备名称*/ #define AHT10_ADDR 0x38 /* 从机地址*/ struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ /* 查找I2C总线设备, 获取I2C总线设备句柄*/ i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); /* 读传感器寄存器数据*/ static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf) { struct rt_i2c_msg msgs; msgs.addr = AHT10_ADDR; /* 从机地址*/ msgs.flags = RT_I2C_RD; /* 读标志*/ msgs.buf = buf; /* 读写数据缓冲区指针 */ msgs.len = len; /* 读写数据字节数*/ /* 调用I2C设备接口传输数据*/ if (rt_i2c_transfer(bus, \u0026amp;msgs, 1) == 1) { return RT_EOK; } else { return -RT_ERROR; } } 七、I2C 总线设备使用示例 I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:\n首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。 控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() 这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 /* * 程序清单: 这是一个I2C 设备使用例程 * 例程导出了i2c_aht10_sample 命令到控制终端 * 命令调用格式: i2c_aht10_sample i2c1 * 命令解释: 命令第二个参数是要使用的I2C总线设备名称, 为空则使用默认的I2C总线设备 * 程序功能: 通过I2C 设备读取温湿度传感器aht10 的温湿度数据并打印 */ #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #define AHT10_I2C_BUS_NAME \u0026#34;i2c1\u0026#34; /* 传感器连接的I2C总线设备名称*/ #define AHT10_ADDR 0x38 /* 从机地址*/ #define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/ #define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/ #define AHT10_GET_DATA 0xAC /* 获取数据命令*/ static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄*/ static rt_bool_t initialized = RT_FALSE; /* 传感器初始化状态*/ /* 写传感器寄存器*/ static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t*data) { rt_uint8_t buf[3]; struct rt_i2c_msg msgs; buf[0] = reg; //cmd buf[1] = data[0]; buf[2] = data[1]; msgs.addr = AHT10_ADDR; msgs.flags = RT_I2C_WR; msgs.buf = buf; msgs.len = 3; /* 调用I2C设备接口传输数据*/ if (rt_i2c_transfer(bus, \u0026amp;msgs, 1) == 1) { return RT_EOK; } else { return -RT_ERROR; } } /* 读传感器寄存器数据*/ static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t*buf) { struct rt_i2c_msg msgs; msgs.addr = AHT10_ADDR; msgs.flags = RT_I2C_RD; msgs.buf = buf; msgs.len = len; /* 调用I2C设备接口传输数据*/ if (rt_i2c_transfer(bus, \u0026amp;msgs, 1) == 1) { return RT_EOK; } else { return -RT_ERROR; } } static void read_temp_humi(float *cur_temp, float *cur_humi) { rt_uint8_t temp[6]; write_reg(i2c_bus, AHT10_GET_DATA, 0); /* 发送命令*/ rt_thread_mdelay(400); read_regs(i2c_bus, 6, temp); /* 获取传感器数据*/ /* 湿度数据转换*/ *cur_humi = (temp[1] \u0026lt;\u0026lt; 12 | temp[2] \u0026lt;\u0026lt; 4 | (temp[3] \u0026amp; 0xf0) \u0026gt;\u0026gt; 4) * 100.0 / (1\u0026lt;\u0026lt; 20); /* 温度数据转换*/ *cur_temp = ((temp[3] \u0026amp; 0xf) \u0026lt;\u0026lt; 16 | temp[4] \u0026lt;\u0026lt; 8 | temp[5]) * 200.0 / (1 \u0026lt;\u0026lt; 20)- 50; } static void aht10_init(const char *name) { rt_uint8_t temp[2] = {0, 0}; /* 查找I2C总线设备, 获取I2C总线设备句柄*/ i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); if (i2c_bus == RT_NULL) { rt_kprintf(\u0026#34;can\u0026#39;t find %s device!\\n\u0026#34;, name); } else { write_reg(i2c_bus, AHT10_NORMAL_CMD, temp); rt_thread_mdelay(400); temp[0] = 0x08; temp[1] = 0x00; write_reg(i2c_bus, AHT10_CALIBRATION_CMD, temp); rt_thread_mdelay(400); initialized = RT_TRUE; } } static void i2c_aht10_sample(int argc, char *argv[]) { float humidity, temperature; char name[RT_NAME_MAX]; humidity = 0.0; temperature = 0.0; if (argc == 2) { rt_strncpy(name, argv[1], RT_NAME_MAX); } else { rt_strncpy(name, AHT10_I2C_BUS_NAME, RT_NAME_MAX); } if (!initialized) { /* 传感器初始化*/ aht10_init(name); } if (initialized) { /* 读取温湿度数据*/ read_temp_humi(\u0026amp;temperature, \u0026amp;humidity); rt_kprintf(\u0026#34;read aht10 sensor humidity : %d.%d %%\\n\u0026#34;, (int)humidity, (int) (humidity * 10) % 10); if( temperature \u0026gt;= 0 ) { rt_kprintf(\u0026#34;read aht10 sensor temperature: %d.%d°C\\n\u0026#34;, (int)temperature, (int)(temperature * 10) % 10); } else { rt_kprintf(\u0026#34;read aht10 sensor temperature: %d.%d°C\\n\u0026#34;, (int)temperature, (int)(-temperature * 10) % 10); } } else { rt_kprintf(\u0026#34;initialize sensor failed!\\n\u0026#34;); } } /* 导出到msh 命令列表中*/ MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample); 学习资料参考:《嵌入式系统设计》、RT-Thread\n","date":"2022-07-15T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/","title":"I2C(内核学习)"},{"content":"一、初识RT-Thread 做世界级的 OS,让万物互联,信息畅通无阻。 成为未来 AIoT 领域最为主流的操作系统平台。\n1.简介 RT-Thread 是一个集实时操作系统(RTOS)内核、中间件组件和开发者社区于一体的技术平台,由熊谱翔先生带领并集合开源社区力量开发而成,RT-Thread 也是一个组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性的物联网操作系统。\n2.前景 RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS。\n3.软件生态 RT-Thread 拥有良好的软件生态,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。\n二、实验准备 编程工具:RT-Thread studio 开发板:潘多拉STM32L475 三、实验需求 1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。 2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。 四、操作流程 1.新建RT-Thread工程 2.RT-Thread Studio界面介绍 3.代码编写 4.烧录 5.串口监视 五、代码演示 1.头文件\n#include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026lt;board.h\u0026gt; 2.宏定义\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //按键初始化 #define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --\u0026gt; KEY #define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --\u0026gt; KEY #define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --\u0026gt; KEY #define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP //电机初始化 #define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A #define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B //蜂鸣器初始化 #define PIN_BEEP GET_PIN(B,2)//PB2:BEEP enum { MOTOR_STOP, MOTOR_LEFT, MOTOR_RIGHT }; 3.void motor_ctrl(rt_uint8_t turn) //电机控制函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void motor_ctrl(rt_uint8_t turn) { if (turn == MOTOR_STOP) { rt_pin_write(PIN_MOTOR_A, PIN_LOW); rt_pin_write(PIN_MOTOR_B, PIN_LOW); } else if (turn == MOTOR_LEFT) { rt_pin_write(PIN_MOTOR_A, PIN_LOW); rt_pin_write(PIN_MOTOR_B, PIN_HIGH); } else if (turn == MOTOR_RIGHT) { rt_pin_write(PIN_MOTOR_A, PIN_HIGH); rt_pin_write(PIN_MOTOR_B, PIN_LOW); } else { rt_kprintf(\u0026#34;err parameter ! Please enter 0-2.\u0026#34;); } } 4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数\n1 2 3 4 5 6 7 8 9 10 11 void beep_ctrl(rt_uint8_t on) { if (on) { rt_pin_write(PIN_BEEP, PIN_HIGH); } else { rt_pin_write(PIN_BEEP, PIN_LOW); } } 5.void irq_callback(void *args) // 中断回调函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void irq_callback(void *args) { rt_uint32_t sign = (rt_uint32_t)args; switch (sign) { case PIN_KEY0: motor_ctrl(MOTOR_LEFT); rt_kprintf(\u0026#34;KEY0 interrupt. motor turn left.\u0026#34;); break; case PIN_KEY1: motor_ctrl(MOTOR_RIGHT); rt_kprintf(\u0026#34;KEY1 interrupt. motor turn right.\u0026#34;); break; case PIN_KEY2: motor_ctrl(MOTOR_STOP); rt_kprintf(\u0026#34;KEY2 interrupt. motor stop.\u0026#34;); break; default: rt_kprintf(\u0026#34;error sign= %d !\u0026#34;, sign); break; } } 5.主函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 int main(void) { unsigned int count = 1; /* 设置按键引脚为输入模式*/ rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); /* 设置电机控制引脚为输入模式*/ rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT); rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT); /* 设置蜂鸣器引脚为输出模式*/ rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT); /* 设置按键中断模式与中断回调函数*/ rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0 ); rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1 ); rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2 ); /* 使能中断*/ rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE); rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE); rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE); while (count \u0026gt; 0) { if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) { rt_thread_mdelay(50); if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) { rt_kprintf(\u0026#34;WK_UP pressed. beep on.\u0026#34;); beep_ctrl(1); } } else { beep_ctrl(0); } rt_thread_mdelay(10); count++; } return 0; } 六、原理讲解 通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。\n按键 功能 KEY0 电机左转 KEY1 电机右转 KEY2 电机停止 WK_UP 蜂鸣器响 ","date":"2022-07-15T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/","title":"RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)"},{"content":"详细原理参考:【玩转RT-Thread】线程管理(详细原理)\n一、线程创建 1、函数原型 1 2 3 4 5 6 7 // 线程创建 rt_thread_t rt_thread_create(const char* name, void (*entry)(void* parameter), void* parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 首先我们来看看线程创建函数返回值类型:\n可以看到线程创建函数的返回值类型为:rt_thread_t,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。\n2、线程定义 那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:\n1 rt_thread_t th1_ptr = NULL 接下来就是我们给进程控制块传参了\n3、线程创建判断 由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功\n我们先来看下线程返回值(如下图)\n如果成功创建的话,返回值是会返回我们所创建的线程对象的\n如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0\n1 2 3 4 5 6 7 8 9 10 // 判断\tif(th1_ptr == RT_NULL) { //错误信息打印 LOG_E(\u0026#34;rt_thread_create create failed...\\n\u0026#34;); return -RT_ENOMEM; // 设定当线程th1_ptr创建失败后,返回一个空间不足的标志 } //打印debug调试信息 LOG_D(\u0026#34;rt_thread_create create successed ...\\n\u0026#34;); 4、线程入口函数 我们在线程的入口处理函数写一个循环函数:\n1 2 3 4 5 6 7 8 void th_entry(void* parameter) { while(1) { rt_kprintf(\u0026#34;th_entry running ...\\n\u0026#34;); rt_thread_mdelay(1000); } } 注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源\n编译,串口观察 由于RTT studio有内置的串口终端,我们直接打开\n终端输入list_thread可以查看所有的线程\n5、总结 这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?\n其实我们再看th_demo线程的状态可以看到是init,参考【玩转RT-Thread】线程管理(详细原理)\n当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT\n其实这句话就表明当线程处于初始化状态下是不参与系统调度的!\n6、补充 线程错误码:\n二、线程启动 函数原型\n在主函数中加入命令,使线程进入就绪态:\n1 rt_thread_startup(th1_ptr); 但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为挂起态\n解释:虽然我们调用rt_thread_startup函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了rt_thread_mdelay函数使其有一定时间的休眠,从而进入了挂起态`\n三、初始化线程 rt_thread_init\n1、函数声明 1 2 3 4 5 6 // 模板函数 rt_err_t rt_thread_init(struct rt_thread* thread, const char* name, void (*entry)(void* parameter), void* parameter, void* stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 2、函数定义 1 ret = rt_thread_init(\u0026amp;th2,\u0026#34;th2_demo\u0026#34;, th2_entry, NULL, th2_stack, sizeof(th2_stack), 19, 5); 此处我们需要定义一个ret整型变量用于rt_thread_init的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。\n3、线程入口函数 代码如下:\n1 2 3 4 5 6 7 8 void th2_entry(void* parameter) { for(i=0;i\u0026lt;10;i++) { rt_kprintf(\u0026#34;th2_entry running ...\\n\u0026#34;); rt_thread_mdelay(1000); } } 4、判断创建状态 静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用rt_thread_startup函数使线程2进入就绪态,并执行线程处理函数。\n1 2 3 4 5 6 7 8 if(ret \u0026lt; 0) { LOG_E(\u0026#34;rt2_thread_create create failed ...\\n\u0026#34;); // 错误信息打印 return ret; } LOG_D(\u0026#34;rt_thread2_create create successes ...\\n\u0026#34;); rt_thread_startup(\u0026amp;th2); // 创建成功后,我们开启线程,使其进入就绪态 这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启\n5、实验结果 分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。\n线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行\n","date":"2022-07-14T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/","title":"RT-Thread Studio使用 2.内核实战篇(线程)"},{"content":"ubuntu安装交叉编译工具链(附避坑指南) 1.打开Ubuntu,在终端进入/usr/local/目录下\ncd /usr/local/ 2.在local/目录下创建一个名为arm的文件夹\nmkdir arm 3.在自己的共享文件夹下找到arm-2009q3.tar.bz2,并复制到之前创建的arm目录下\ncp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/ 4.进入到arm目录下,解压该其中文件\ncd /usr/local/arm tar -jxvf arm-2009q3.tar.bz2\t5.然后执行:\ncd arm-2009q3/bin ./arm-none-linux-gnueabi-gcc -v 注意:这里如果输入./arm-none-linux-gnueabi-gcc -v终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持\nsudo apt-get install libc6:i386 安装好了之后重新输入./arm-none-linux-gnueabi-gcc -v 操作成功!\n6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 打开配置文件\nsudo vim /etc/profile 7.在vi界面末尾处加入\nexport PATH=$PATH:/usr/local/arm/arm-2009q3/bin 8.回到主目录,查看交叉编译工具是否可用\ncd ~ source /etc/profile 注 这里如果没有出现相关信息,切换root用户再次输入命令\n使用\techo $PATH查看交叉编译链的安装路径是否加入了环境变量。 使用arm-linux-gnueabihf-gcc -v测试交叉编译链是否好使\n9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:\nchmod 777 mk-arm-linux-.sh ./mk-arm-linux-.sh 这里由于运行时报错,原因详见解决linux的-bash: ./xx.sh: Permission denied\nls查看,可以发现符号链接出现,到此,交叉编译链配置成功!\n附件:\narm-2009q3.tar.bz2\nmk-arm-linux-.sh脚本文件\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line ln arm-none-linux-gnueabi-ar -s arm-linux-ar ln arm-none-linux-gnueabi-as -s arm-linux-as ln arm-none-linux-gnueabi-c++ -s arm-linux-c++ ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp ln arm-none-linux-gnueabi-g++ -s arm-linux-g++ ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1 ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof ln arm-none-linux-gnueabi-ld -s arm-linux-ld ln arm-none-linux-gnueabi-nm -s arm-linux-nm ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf ln arm-none-linux-gnueabi-size -s arm-linux-size ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite ln arm-none-linux-gnueabi-strings -s arm-linux-strings ln arm-none-linux-gnueabi-strip -s arm-linux-strip 有问题欢迎评论留言致信:blogs\n","date":"2022-07-14T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/","title":"ubuntu安装交叉编译工具链"},{"content":"恢复ubuntu20.04默认桌面管理器 一、GDM, KDM, LightDM, SDDM的区别和安装配置 1、GDM,gnome系列的图形管理器 2、KDM,SDDM是KDE系列的图形管理器 3、LightDM 二、配置和切换 三、恢复ubuntu20.04默认桌面管理器 1、打开终端,用管理员口令下载相关资源 2、安装gnome-shell 3、安装ubuntu-gnome-desktop 4、安装unity-tweak-tool和gnome-tweak-tool 5、安装完成后重启 起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能远程控制桌面了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(gnome图形管理器)也变成了我不喜欢的风格(轻量级的LightDM)了,大家以后要慎重。\n注意:我是个半吊子,仅供参考。\n一、GDM, KDM, LightDM, SDDM的区别和安装配置 GDM, KDM, LightDM, SDDM的区别和安装配置\ngdm3,kdm 和 lightdm 都是显示管理器。 它们提供图形化登录并处理用户身份验证。\n1、GDM,gnome系列的图形管理器 1 sudo apt-get install gdm3 1 sudo apt-get remove gdm3 2、KDM,SDDM是KDE系列的图形管理器 kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。\n1 sudo apt-get install sddm 1 sudo apt-get remove sddm 3、LightDM LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。\n1 sudo apt-get install lightdm 1 sudo apt-get remove lightdm 二、配置和切换 1 sudo dpkg-reconfigure gdm3 你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。\n要检查当前正在使用的显示管理器,请运行以下命令:\n1 cat /etc/X11/default-display-manager Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:\n1 sudo dpkg-reconfigure lightdm Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:\n1 sudo dpkg-reconfigure lightdm GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。\n三、恢复ubuntu20.04默认桌面管理器 恢复ubuntu20.04默认桌面管理器\n目前Ubuntu的主流桌面GNOME, Ubntu的内置桌面是Untiy\n1、打开终端,用管理员口令下载相关资源 1 Ctrl+Alt+T 打开终端,用管理员口令下载相关资源\n2、安装gnome-shell 1 sudo apt-get install gnome-shell 提示:\n管理员权限需要输入密码,但是系统不会显示你输入的密码\n输入完成后,直接回车即可\n3、安装ubuntu-gnome-desktop 1 sudo apt-get install ubuntu-gnome-desktop 4、安装unity-tweak-tool和gnome-tweak-tool 1 sudo apt-get install unity-tweak-tool 1 sudo apt-get install gnome-tweak-tool 5、安装完成后重启 然后一切恢复如初,仿佛没发生过。\n","date":"2022-07-14T00:00:00Z","image":"https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/","title":"ubuntu桌面恢复(20.04)"},{"content":"1. 安装x11vnc 1 sudo apt-get install x11vnc -y 直接安装成功。\n2. 设置vnc密码 密码存储在/etc/目录里面\n1 sudo x11vnc -storepasswd /etc/x11vnc.pass 放在这个位置,需要设置文件读取权限\n否则会提示密码校验失败\n1 sudo chmod 777 /etc/x11vnc.pass 3.创建vnc配置文件 在/etc/init 下创建一个x11vnc.conf的文件\n1 2 cd /etc/init sudo gedit x11vnc.conf 文件内容如下:\n1 2 3 4 5 6 #description \u0026#34;xiaoqiang vnc server\u0026#34; #start on runlevel [2345] #stop on runlevel [06] #script exec /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport 5900 -shared #end script 我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。\n4.启动vnc服务 1 source /etc/init/x11vnc.conf 启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了\n5.设置自启动 我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。\n(1)首先编写一个脚本 1 gedit x11vnc.sh 添加以下内容\n第一行是要添加的解释器,后面是要执行的指令内容\n1 2 #!/bin/bash source /etc/init/x11vnc.conf 防止误删,从home移动到/etc/init.d/文件夹中\n并添加权限\n1 2 sudo mv x11vnc.sh /etc/init.d/ sudo chmod 777 /etc/init.d/x11vnc.sh (2)添加启动项 点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。\n点击右侧添加,添加自动启动项。\n添加内容如下;重要的是第二行,\n1 bash /etc/init.d/x11vnc.sh 用bash启动才能成功,保存之后重启,确实可以开机自启了。\n6.x11vnc配置(安装虚拟显卡驱动) 如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示\n(1)首先还是安装命令 1 sudo apt-get install xserver-xorg-video-dummy (2)接下来就是创建配置文件 /etc/X11/xorg.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Section \u0026#34;Device\u0026#34; Identifier \u0026#34;Dummy\u0026#34; Driver \u0026#34;dummy\u0026#34; VideoRam 64000 Option \u0026#34;IgnoreEDID\u0026#34; \u0026#34;true\u0026#34; Option \u0026#34;NoDDC\u0026#34; \u0026#34;true\u0026#34; EndSection Section \u0026#34;Monitor\u0026#34; Identifier \u0026#34;Monitor\u0026#34; HorizSync 15.0-100.0 VertRefresh 15.0-200.0 EndSection Section \u0026#34;Screen\u0026#34; Identifier \u0026#34;Screen\u0026#34; Monitor \u0026#34;Monitor\u0026#34; Device \u0026#34;Dummy\u0026#34; DefaultDepth 24 SubSection \u0026#34;Display\u0026#34; Depth 24 Modes \u0026#34;1280x720\u0026#34; EndSubSection EndSection (3)再修改个文件加点配置 1 vi /boot/firmware/usercfg.txt 1 2 framebuffer_width=1280 framebuffer_height=720 如果想要恢复显示器的连接,可以先使用ssh访问终端并将/etc/X11/xorg.conf这个文件删除,再次重启即可\n","date":"2022-07-14T00:00:00Z","image":"https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/cover_hu1f665307cfc2974f92d9a28bfa39459d_48351_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/","title":"x11vnc安装与配置"},{"content":"一、时钟节拍 任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。\nRT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!\nrtconfig.h配置文件中定义:\n频率是1000HZ周期是1/1000 s\n所以节拍是1ms\n#define RT_ TiCK PER_ SECOND 1000\n1、void SysTick_Handler() 在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行void SysTick_Handler(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)\n可以发现在void SysTick_Handler()这个函数中,首先会执行中断入口函数,然后void rt_tick_increase对rt_tick(系统滴答时钟,初值为0,静态全局变量)进行自加操作,会记录从启动到现在的时钟节拍数\n2、void rt_tick_increase() 也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断 3、rt_tick_get(void); 名称:获取系统统计函数\n功能:返回当前操作系统的时钟数\n返回值:返回当前时钟数\n二、定时器管理 1、概念 定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有硬件定时器和软件定时器之分:\n1)硬件定时器是芯片本身提供的定时功能。一般是由外部晶振(HSE)提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。\n2)软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。\nRT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时数值必须是 OS Tick 的整数倍,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。\n2、RT-Thread定时器介绍 RT-Thread 的定时器提供两类定时器机制:\n第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远持续执行下去。\n另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 HARD_TIMER 模式(硬件定时器模式)与 SOFT_TIMER 模式(软件定时器模式),如下图。\n1)HARD_TIMER 模式:中断上下文\nHARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数RT_TIMER_FLAG_HARD_TIMER来指定。\n在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。\n2)SOFT_TIMER 模式:线程上下文\nSOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。\n该模式被启用后,系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。\n3、定时器源码分析 1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数\n2)rt_system_timer_init(硬件定时器初始化)\n1 2 3 4 5 6 7 8 9 void rt_system_timer_init(void) { int i;// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入 for (i = 0; i \u0026lt; sizeof(rt_timer_list) / sizeof(rt_timer_list[0]); i++) { rt_list_init(rt_timer_list + i); } } 3)rt_system_timer_thread_init(软件定时器初始化)\n4、定时器工作机制 下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的全局变量:\n(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);\n(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到 rt_timer_list 链表中。\n如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。\n而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),50 个 tick 以后,rt_tick 从 20 增长到 70,与 Timer1 的 timeout 值相等,这时会触发与 Timer1 定时器相关联的超时函数,同时将 Timer1 从 rt_timer_list 链表上删除。\n同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。\n如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 timeout=rt_tick+300=330, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:\n5、定时器相关接口 1)动态创建定时器\n动态创建声明:\n1 2 3 4 5 rt_timer_t rt_timer_create(const char *name, void (*timeout)(void *parameter), void *parameter, rt_tick_t time, rt_uint8_t flag); 详细函数定义:\n查看flag定义:\n1 2 3 4 5 #define RT_TIMER_FLAG_ONE_SHOT 0x0 // 单次触发 #define RT_TIMER_FLAG_PERIODIC 0x2 // 周期性触发 #define RT_TIMER_FLAG_HARD_TIMER 0x0 // 硬件定时器模式 #define RT_TIMER_FLAG_SOFT_TIMER 0x4\t// 软件定时器模式 同时这里我们注意到rt_timer_create这个函数的返回值是rt_timer_t,通过查找定义可以发现该类型是通过typedef重命名的\n也就是说struct rt_timer \u0026lt;=\u0026gt;*rt_timer_t\n1 typedef struct rt_timer *rt_timer_t; 下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述\n1 2 3 4 5 6 7 8 9 10 11 12 struct rt_timer { struct rt_object parent; /**\u0026lt; inherit from rt_object */ rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; void (*timeout_func)(void *parameter); /**\u0026lt; timeout function */ void *parameter; /**\u0026lt; timeout function\u0026#39;s parameter */ rt_tick_t init_tick; /**\u0026lt; timer timeout tick */ rt_tick_t timeout_tick; /**\u0026lt; timeout tick */ }; 2)删除定时器\n函数声明:\n1 rt_err_t rt_timer_delete(rt_timer_t timer); 函数返回值:返回操作系统的状态,成功返回0,失败返回1\n3)动态创建定时器演示\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 主函数 int main(void) { tm = rt_timer_create(\u0026#34;tm_demo\u0026#34;,tm_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); if(tm == RT_NULL) { LOG_E(\u0026#34;rt_timer_create faile...\\n\u0026#34;); return -ENOMEM; } LOG_D(\u0026#34;rt_timer_create successed...\\n\u0026#34;); return 0; } 在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义\t)。\n1 2 3 4 5 6 // 编写中断回调函数(超时函数) void tm_callback(void *parameter) { } 1 2 3 // 返回值结构图定义 rt_timer_t tm ; 4)开启定时器\n函数声明:\n1 rt_err_t rt_timer_start(rt_timer_t timer); 函数返回值:成功返回0,失败返回1\n5)实例:\n1 rt_timer_start(tm); 此时我们在超时函数中编写代码:\n1 2 3 4 void tm_callback(void *parameter) { rt_kprintf(\u0026#34;tm_callback is running...\\n\u0026#34;); } 此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息\n6)静态创建定时器\n函数定义:\n1 2 3 4 5 6 void rt_timer_init(rt_timer_t timer, const char *name, void (*timeout)(void *parameter), void *parameter, rt_tick_t time, rt_uint8_t flag); 这里我们看下rt_timer_init这个函数的返回值和参数\n返回值:void\n参数:\n参数 描述 timer 结构体指针类型 name 名字 timeout 超时回调函数指针 parameter 传递给超时回调函数的参数 time 定时器时间 flag 定时器标志 7)脱离函数(静态创建时使用)\n描述:当静态创建的定时器不需要在使用时,我们调用下面这个函数接口\n函数声明:\n1 rt_err_t rt_timer_detach(rt_timer_t timer); 返回值:成功返回0,失败返回1\n8)定时器控制\n函数声明:\n1 rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg); cmd命令定义查看\n1 2 3 4 5 #define RT_TIMER_CTRL_SET_TIME 0x0 /**\u0026lt; set timer control command */ #define RT_TIMER_CTRL_GET_TIME 0x1 /**\u0026lt; get timer control command */ #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /**\u0026lt; change timer to one shot */ #define RT_TIMER_CTRL_SET_PERIODIC 0x3 /**\u0026lt; change timer to periodic */ #define RT_TIMER_CTRL_GET_STATE 0x4 /**\u0026lt; get timer run state active or deactive*/ 实例:\n查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include \u0026lt;rtthread.h\u0026gt; #include \u0026lt;rtdevice.h\u0026gt; #include \u0026lt;board.h\u0026gt; #include \u0026lt;rtdbg.h\u0026gt; rt_timer_t tm ; struct rt_timer tm2 ; int flags = 0; void tm_callback(void *parameter) { rt_kprintf(\u0026#34;tm_callback is running...\\n\u0026#34;); } void tm2_callback(void *parameter) { flags++; if(flags == 10)// 当flags标志位位10时,设置单次触发 { rt_timer_control(\u0026amp;tm2, RT_TIMER_CTRL_SET_ONESHOT, NULL); flags = 0; } rt_tick_t timeout = 1000; rt_timer_control(\u0026amp;tm2, RT_TIMER_CTRL_SET_TIME, (void *)\u0026amp;timeout); rt_kprintf(\u0026#34;[%u]tm2_callback is running...\\n\u0026#34;,rt_tick_get()); } int main(void) { // 动态创建定时器 tm = rt_timer_create(\u0026#34;tm_demo\u0026#34;,tm_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); if(tm == RT_NULL) { LOG_E(\u0026#34;rt_timer_create faile...\\n\u0026#34;); return -ENOMEM; } LOG_D(\u0026#34;rt_timer_create successed...\\n\u0026#34;); rt_timer_start(tm); // 静态创建定时器 rt_timer_init(\u0026amp;tm2,\u0026#34;tm2_demo\u0026#34;,tm2_callback,NULL,3000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); rt_timer_start(\u0026amp;tm2); return 0; } 三、高精度延时 注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间\n函数声明:void rt_hw_us_delay(rt_uint32_t us); 应用场景:应用于某些场景下对高精度延时有要求的情况下 ","date":"2022-07-13T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/","title":"时钟管理(原理+实战)"},{"content":"一、基础配置 1.首先需要下载git并配置好相应的环境变量\n2.双击env,在setting中设置\n这样就可以指定文件夹打开env工具了\n二、基本命令学习 1.scons:编译\n(1)scons:编译并打印相关内部信息 (2)scons -c:清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 (3)scons -s:编译而不打印具体的内部命令 (4)scons --target=XXX:使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载\n1 2 3 scons --target=iar scons --target=mdk4 scons --target=mdk5 (5)scons -jN:多线程编译目标,在多核计算机上可以使用此命令加快编译速度\n1 scons -j4 //双核编译工程 注意:一般不建议使用,容易将编译信息和错误混杂 (6)scons --dist:搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 2.指定编译器安装路径\n1 2 set RTT_CC=keil set RTT_EXEC_PATH=C:/Keilv5 3.menuconfig 打开菜单配置界面,可用户自定义模块\n4.scons进阶学习 scons内置函数\nGetCurrentDir(): 获取当前路径。\nGlob(\u0026rsquo;*.c\u0026rsquo;): 获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。\nGetDepend(macro): 该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。\nSplit(str): 将字符串 str 分割成一个列表 list。\nDefineGroup(name, src, depend,**parameters): 这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 DefineGroup() 函数的参数描述:\n参数 描述 name Group 的名字 src Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件 depend Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现 parameters 配置其他参数,可取值见下表,实际使用时不需要配置所有参数 parameters可加入的参数:\n参数 描述 dirs SConscript 文件路径 variant_dir 指定生成的目标文件的存放路径 duiplicate 设定是否拷贝或链接源文件到 variant_dir ","date":"2022-05-12T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover_hu40687f202fa630f90f24f65ce5d02641_5793_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/","title":"env工具学习"},{"content":"1、Microsoft Visual C++ 14.0安装 这里附上百度网盘下载链接: 链接: https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88 提取码: ec88\n下载完成后双击打开 默认下载方式即可\n2、Pycocotools2.0版本安装 (1)准备材料: 下载pycocotools安装包(可直接git拉取到本地文件夹) (2)源码配置 打开下载好的pycocotools,双击打开setup.py(文件路径:\\cocoapi\\PythonAPI\\setup.py)\n这里将蓝色部分删除,只保留红色部分(切记需要执行这一步!!!)\n开始界面找到所有应用并打开Anaconda Powershell Prompt\n先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。\n如上图所示进入到\\cocoapi\\PythonAPI该目录下\n分别执行以下两个命令:\n1 2 python setup.py build_ext --inplace python setup.py build_ext install 执行pip list查看\n此时回到\\cocoapi\\PythonAPI目录下,可以看到生成了相关文件 将pycocotools和pycocotools.egg-info文件夹复制到你所创建的虚拟环境中(位置:Anaconda3-\u0026gt;envs-\u0026gt;python_env-\u0026gt;Lib-\u0026gt;site-packages) 至此所有问题解决!\n","date":"2022-04-12T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/","title":"Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)"},{"content":"一、桥接网络 1、简介 是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址\n注意避坑: 如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。\n2、解决办法: \u0026lt;1\u0026gt;选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。\n\u0026lt;2\u0026gt;无线网卡连接\n考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)\n如下配置:\n主机配置 首先电脑win+R,输入cmd进入终端,然后输入命令:ipconfig,找到自己的热点网络信息\n虚拟机配置 1 ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces 1 2 3 保存退出后,再次输入命令: 首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡) 然后启用网卡:ifup eth0 二、开发板端测试: 以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客\n【Linux系统开发】x210开发板根目录文件系统构建\n我们打开secureCRT:\n开机先ping下虚拟机网络:ping '虚拟机IP'\n注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 方法一:打开命令:sudo gedit /etc/NetworkManager/nm-system-settings.conf 出现文件内容: # This file is installed into /etc/NetworkManager, and is loaded by # NetworkManager by default. To override, specify: \u0026#39;--config file\u0026#39; # during NM startup. This can be done by appending to DAEMON_OPTS in # the file: # # /etc/default/NetworkManager # [main] plugins=ifupdown,keyfile [ifupdown] managed=true (这里false改成true) 1 2 3 4 5 6 7 方法二:虚拟机重置网卡 sudo /etc/init.d/networking restart sudo /etc/init.d/networking start ifdown eth0 ifup eth0 当开发板ping通虚拟机后,我们在secureCRT控制台输入reset命令重启开发板\n这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应\n解决:\n1 2 3 4 5 mount -t nfs -o nolock \u0026#39;开发板ipaddr ip\u0026#39;:/root/rootfs/x210_rootfs //再次重新挂载根文件系统 //NFC网络重启 /etc/init.d/nfs-kernel-server restart sudo /etc/init.d/networking start 问题解决!\n","date":"2022-03-30T00:00:00Z","image":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/cover_hu4f94b71a165b962db7609fb23d2e6f56_29527_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/","title":"总结:开发板挂载根文件系统遇到的一些问题"},{"content":"1.Linux多线程概念 (1)线程:指运行中的程序的调度单位。\n(2)多线程的优点:\n运行与一个线程中的多个线程,他们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。 进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式 应用程序响应速度提高 使多CPU系统更加高效 改善程序结构 (3)线程的生命周期\n就绪-\u0026gt;运行-\u0026gt;阻塞-\u0026gt;终止\n2.linux线程实现 (1)线程创建\n头文件包含 #include \u0026lt;pthread.h\u0026gt;\n定义函数:\nint pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) 函数说明: tidp:线程id attr:线程属性(通常为空) start_rtn:线程要执行的函数 arg: start_rtn的参数\n(2)线程退出\n头文件包含: #include \u0026lt;pthread.h\u0026gt; 定义函数: void pthread_exit(void * rval_ptr) 功能:终止调用线程Rval_ptr:线程退出返回值的指针。 (3)线程等待\n头文件包含: #include \u0026lt;pthread.h\u0026gt;\n定义函数:\nint pthread_join(pthread_t tid,void **rval_ptr) 功能:阻塞调用线程,直到指定的线程终止。\n函数说明: Tid :等待退出的线程id Rval_ptr:线程退出的返回值的指针\n(4)线程标识获取\n头文件包含: #include \u0026lt;pthread.h\u0026gt; 定义函数: pthread_t pthread_self(void) 功能:获取调用线程的 thread identifier (5)线程清除\n头文件包含: #include \u0026lt;pthread.h\u0026gt;\n定义函数:\nvoid pthread_cleanup_push(void (*rtn)(void *),void *arg) 功能:将清除函数压入清除栈\n函数说明: Rtn:清除函数 Arg:清除函数的参数\n3.线程同步的方法 进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:\n互斥量(互斥锁)Mutex 信号灯(信号量)Semaphore 条件变量Conditions\n4.线程的互斥 线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。\n(1)创建\n在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:\n对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER 对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。 函数使用: 头文件: #include \u0026lt;pthread.h\u0026gt;\nint pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) int pthread_mutex_destroy(pthread_mutex_t *mutex) (2)加锁\n对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。\n函数使用:\nint pthread_mutex_lock(pthread_mutex_t *mutex) int pthread_mutex_trylock(pthread_mutex_t *mutex) 返回值: 成功则返回0, 出错则返回错误编号. 注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。\n(3)解锁\n在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。\nint pthread_mutex_unlock(pthread_mutex_t *mutex) 5.互斥PK信号量 Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 Binary semaphore与Mutex的差异:\nmutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放 初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。 6.信号量操作(代码演示) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;pthread.h\u0026gt; #include\u0026lt;stdlib.h\u0026gt; #include\u0026lt;semaphore.h\u0026gt; //子线程处理 char buf[200]; sem_t sem; int flag; void *func(void *arg) { sem_wait(\u0026amp;sem); // 接收信号量 /* Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 */ //while(strncmp(buf,\u0026#34;end\u0026#34;,3) != 0) while(flag == 0) { printf(\u0026#34;input %d char.\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); } pthread_exit(NULL); } int main(void) { int ret = -1; pthread_t th = -1; sem_init(\u0026amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 ret = pthread_create(\u0026amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 if(ret != 0) { printf(\u0026#34;pthread_create error.\\n\u0026#34;); return -1; } printf(\u0026#34;please input string,end with Enter.\\n\u0026#34;); while(scanf(\u0026#34;%s\u0026#34;,buf)) { if(!strncmp(buf,\u0026#34;end\u0026#34;,3)) { printf(\u0026#34;process end\\n\u0026#34;); flag = 1; sem_post(\u0026amp;sem); //增加(解锁)sem指向的信号量 break; } printf(\u0026#34;input %d char .\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); } printf(\u0026#34;wait reclaim child thread.\\n\u0026#34;); ret = pthread_join(th,NULL); if(ret != 0) { printf(\u0026#34;pthread_join error.\\n\u0026#34;); exit(-1); } printf(\u0026#34;reclaim child thread successfully.\\n\u0026#34;); return 0; } 7.互斥操作(函数演示) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;pthread.h\u0026gt; #include\u0026lt;stdlib.h\u0026gt; //子线程处理 char buf[200]; pthread_mutex_t mutex; int flag; void *func(void *arg) { sleep(1); while(flag == 0) { pthread_mutex_lock(\u0026amp;mutex);// 互斥加锁 printf(\u0026#34;input %d char.\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); pthread_mutex_unlock(\u0026amp;mutex); // 解锁 } pthread_exit(NULL); } int main(void) { int ret = -1; pthread_t th = -1; pthread_mutex_init(\u0026amp;mutex,NULL); ret = pthread_create(\u0026amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 if(ret != 0) { printf(\u0026#34;pthread_create error.\\n\u0026#34;); return -1; } printf(\u0026#34;please input string,end with Enter.\\n\u0026#34;); while(1) { pthread_mutex_lock(\u0026amp;mutex);// 对互斥对象加锁锁定 scanf(\u0026#34;%s\u0026#34;,buf); pthread_mutex_unlock(\u0026amp;mutex); // 输入后解锁 if(!strncmp(buf,\u0026#34;end\u0026#34;,3)) { printf(\u0026#34;process end\\n\u0026#34;); flag = 1; break; } printf(\u0026#34;input %d char .\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); } printf(\u0026#34;wait reclaim child thread.\\n\u0026#34;); ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 if(ret != 0) { printf(\u0026#34;pthread_join error.\\n\u0026#34;); exit(-1); } printf(\u0026#34;reclaim child thread successfully.\\n\u0026#34;); pthread_mutex_destroy(\u0026amp;mutex); return 0; } 8.条件变量(代码演示) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;pthread.h\u0026gt; #include\u0026lt;stdlib.h\u0026gt; //子线程处理 char buf[200]; pthread_mutex_t mutex; pthread_cond_t cond; int flag; void *func(void *arg) { while(flag == 0) { pthread_mutex_lock(\u0026amp;mutex);// 互斥加锁 pthread_cond_wait(\u0026amp;cond,NULL);// 线程同步等待 printf(\u0026#34;input %d char.\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); pthread_mutex_unlock(\u0026amp;mutex); // 解锁 } pthread_exit(NULL); } int main(void) { int ret = -1; pthread_t th = -1; pthread_mutex_init(\u0026amp;mutex,NULL); pthread_cond_init(\u0026amp;cond,NULL); //初始化条件变量 ret = pthread_create(\u0026amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 if(ret != 0) { printf(\u0026#34;pthread_create error.\\n\u0026#34;); return -1; } printf(\u0026#34;please input string,end with Enter.\\n\u0026#34;); while(1) { scanf(\u0026#34;%s\u0026#34;,buf); pthread_cond_signal(\u0026amp;cond);// 发送信号 if(!strncmp(buf,\u0026#34;end\u0026#34;,3)) { printf(\u0026#34;process end\\n\u0026#34;); flag = 1; break; } printf(\u0026#34;input %d char .\\n\u0026#34;,strlen(buf)); memset(buf,0,sizeof(buf)); } printf(\u0026#34;wait reclaim child thread.\\n\u0026#34;); ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 if(ret != 0) { printf(\u0026#34;pthread_join error.\\n\u0026#34;); exit(-1); } printf(\u0026#34;reclaim child thread successfully.\\n\u0026#34;); pthread_mutex_destroy(\u0026amp;mutex); pthread_cond_destroy(\u0026amp;cond);// 条件变量销毁 return 0; } ","date":"2022-03-22T00:00:00Z","image":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/","title":"多线程技术学习(基于Linux)"},{"content":"信号量 一个特殊变量 用于进程间传递信息的一个整数值 定义如下:\n1 2 3 4 5 struct semaphore { int count; quenue Type quenue; } 信号量说明:semaphore s; 对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen)) P、V操作定义 P(s)\n1 2 3 4 5 6 7 8 9 { s.count --; //信号量值减一 if(s.count\u0026lt;0) { 该进程状态置为阻塞态; 将该进程插入相应的等待队列s.quenue末尾; 重新调度 } } down,semwait:也代表P操作\nV(s)\n1 2 3 4 5 6 7 8 { s.ount++; if(s.count\u0026lt;=0) { 唤醒相应等待队列s.queue中等待的一个进程; 改变其状态为就绪态,并将其插入就绪队列; } } up,semsignal:也代表V操作\n相关说明\nP,V操作为原语操作 在信号量上定义了三个操作 初始化(非负数)、P操作、V操作 最初提出的是二元信号量(解决互斥) 之后,推广到一般信号量(多值)或技术信号量(解决同步) 用PV操作解决进程间互斥问题 分析并发进程的关键活动,划定临界区 设置信号量mutux,初值为1 在临界区前实施P(mutux) 在临界区之后实施V(mutux) 相关解释:\n临界区 : 我们把并发进程中与共享变量有关的程序段称为临界区。\n信号量 : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。\n进程的互斥:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。\n进程的同步:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。\npv操作又称wait,signal原语。 主要是操作进程中对进程控制的信息量的加减控制。\n注意:在霍尔管程中,wait操作和signal操作用于被设计为两个可以中断的过程,而非原语。 在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 条件变量的两种操作:\nwait()操作[阻塞调用进程] signal()操作[释放/唤醒在条件变量上阻塞的进程] wait用法: wait(num),num是目标参数,wait的作用是使其(信息量)减一。 如果信息量\u0026gt;=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 signal用法: signal(num),num是目标参数,signal的作用是使其(信息量)加一。 如果信息量\u0026gt;0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。 本文资源来自Operating Systems 参考:操作系统P,V(wait,signal原语)操作讲解\n","date":"2022-03-10T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/","title":"信号量及PV操作详解"},{"content":"进程 操作系统资源分配的基本单位,也就是指计算机中已执行的程序。\n在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,进程是程序的基本执行实体; 在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是线程的容器。 程序本身只是指令、数据及其组织形式的描述,相当于一个名词,进程才是程序(那些指令和数据)的真正执行实例. 进程上下文 进程上下文就是表示进程信息的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。\n拿Linux进程举例: \u0026mdash;-进程的运行环境主要包括:\n1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 2.环境变量:提供进程运行所需的环境信息。 3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 4.进程访问设备或者文件时的权限。 5.各种硬件寄存器。 6.地址转换信息。\n由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。\n线程 操作系统能够进行运算调度的最小单位。\n大部分情况下,它被包含在进程之中,是进程中的实际运作单位。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 线程是独立调度和分派的基本单位。 线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。 同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 线程上下文 进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。同样的,线程也有上下文。\n当线程被抢占时,就会发生线程之间的上下文切换。 如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。\n线程上下文与进程上下文对比\n上下文内容 进程 线程 指向可执行文件的指针 × 栈 × × 内存(数据段和堆) × 状态 × × 优先级 × × 程序IO的状态 × 授予权限 × 调度信息 × 审计信息 × 文件描述符 × 文件读/写指针 × 寄存器组 × × ","date":"2022-03-08T00:00:00Z","image":"https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/cover_hu21d07300cfd1bfb4ad034fbcbe6552b7_47584_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/","title":"进程上下文和线程上下文"},{"content":"基本格式 1 2 3 4 5 6 7 8 #include \u0026lt;iostream\u0026gt; using namespace std; int main(){ std::cout \u0026lt;\u0026lt; \u0026#34;hello world!\u0026#34; \u0026lt;\u0026lt; endl; cout \u0026lt;\u0026lt; \u0026#34;hello world!\\n\u0026#34;; return 0; } 编译预处理命令: #include \u0026lt;iostream\u0026gt;(输入输出流) 命令空间 using namespace std; cin \u0026gt;\u0026gt; :用于输入;cout \u0026lt;\u0026lt; :用于输出; endl:用于换行 源文件扩展名.cpp 目标代码文件(编译后)扩展名.obj 可执行文件(链接后).exe 特点 C++与C完全兼容,是C的扩展和改革 支持面向对象程序设计 生成的代码质量高 C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:抽象、封装、继承和多态。 C++数据类型 主要分为三类:基本数据类型、构造数据类型、类\n基本数据类型 整型 实型(浮点型) 字符型 布尔型 void型 构造数据类型 数组类型 指针类型 枚举类型 结构体类型 共用体类型 类 \u0026hellip; 函数重载 简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。\n如:\n1 2 double area(double a, double b); double area(double r); 注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生 类和对象* 1.类 类由说明部分和实现部分组成,其说明部分的形式如下:\n1 2 3 4 5 6 7 8 9 10 11 class 类名 { private: 成员表1; protected: 成员表2; public: 成员表3; }; 实现部分的形式如下:\n1 2 3 4 类名::成员函数名(形参表) { 函数体; } 注意:在类内不能对数据成员进行初始化,同时,private\\protect\\public三个关键字对数据成员有不同的访问控制\nprivate:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员; public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口 protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据 2.类的成员函数 类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:\n1 2 3 4 类型 类名::函数成员名(参数表) { 函数体 } 其中::被称为作用域运算符,能指出函数成员是属于哪个类的\n3.类的对象 含义 如果把类看作是数据类型,则该数据类型定义的变量就是对象。\n格式 在定义类之后,就可以定义对象了,一般格式为:\n1 类名 对象名1,对象名2,...; 也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象\n对象的使用 对于一般对象(非对象指针),访问其成员的方式为:\n1 对象名.共有数据成员名(或共有成员函数名/参数表) 对于指向对象的指针,访问其成员的方式为:\n1 对象指针名-\u0026gt;共有数据成员名(或共有成员函数名/参数表) 注意:其中.为点运算符;-\u0026gt;为箭头运算符(类似结构体)\n示例 在主函数中调用Clock类中的show()函数,可写成如下形式:\n1 2 3 4 5 Clock P, *p = \u0026amp;P;//定义对象P以及指向P的指针p P.show();\t//调用对象P的show()函数成员 P-\u0026gt;show();\t//调用指针P指向的show()函数成员 (*p).show();//调用指针p指向的内容P的show()函数成员 类的访问权限 继承方式 基类的public成员 基类的protected成员 基类的private成员 继承引起的访问控制关系变化概括 public继承 仍为public成员 仍为protected成员 不可见 基类的非私有成员在子类的访问属性不变 protected继承 变为protected成员 变为protected成员 不可见 基类的非私有成员都为子类的保护成员 private继承 变为private成员 变为private成员 不可见 基类中的非私有成员都称为子类的私有成员 构造函数与析构函数 1.构造函数 含义 构造函数的功能是将对象初始化,其特点是与类同名,且无返回类型\n格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ... public: Clock(int newC,int newN,int newM);\t//类中声明构造函数 ... Clock::Clock(int newC,int newN,int newM) { c = newC; n = newN; m = newM; } int main() { Clock p(0,0,0);\t//主函数中调用构造函数来初始化对象P P.show();\t//对象P调用成员函数show()来完成其他目的 return 0; } 2.析构函数 含义 类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。\n析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。\n只要类的对象被销毁,就会调用该类的析构函数。\n作用 析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。\n示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include \u0026lt;iostream\u0026gt; using namespace std; class Line { public: void setLength(double len); double getLength(void); Line();\t//这是构造函数声明 ~Line();\t//这是析构函数声明 private: double length; }; Line::Line(void) { cout \u0026lt;\u0026lt; \u0026#34;object is being created\u0026#34; \u0026lt;\u0026lt; endl; } Line::~Line(void) { cout \u0026lt;\u0026lt; \u0026#34;object is being deleted\u0026#34; \u0026lt;\u0026lt; endl; } void Line::setLength(double len) { length = len; } double Line::getLength(void) { return length; } int main() { Line line; line.setLength(6.0); cout \u0026lt;\u0026lt; \u0026#34;length of line :\u0026#34; \u0026lt;\u0026lt; line.getLength() \u0026lt;\u0026lt; endl; return 0;\t//main函数返回前,line对象会被自动销毁 } 拷贝(复制)构造函数 含义 拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。\n拷贝构造函数常用于:\n通过使用另一个同类型的对象来初始化新创建的对象 复制对象把它作为参数传递给函数 复制对象,并从函数返回这个对象 格式 如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。\n拷贝构造函数的常见形式如下:\n1 2 3 4 classname (const classname \u0026amp;obj) { // 构造函数的主体 } 拷贝构造函数的触发 在C++中,主要有以下几种情况会调用拷贝构造函数:\n1.使用一个同类型对象初始化另一个对象时 1 2 MyClass obj1(10); MyClass obj2(obj1); // 调用拷贝构造函数 2.以值传递的方式将一个对象作为参数传递给函数时 1 2 3 4 5 6 void myFunc(MyClass obj) { // 函数接收到的obj是调用拷贝构造函数创建的 } MyClass obj(10); myFunc(obj); 3.返回局部对象时 1 2 3 4 MyClass myFunc() { MyClass ret(10); return ret; // 调用拷贝构造函数后返回 } 4.编译器优化时会让临时对象调用拷贝构造函数 1 MyClass(10) + MyClass(20); // 两个临时对象会调用拷贝构造函数 5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 1 2 3 std::vector\u0026lt;MyClass\u0026gt; vec; MyClass obj(10); vec.push_back(obj); 以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。\n示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include \u0026lt;iostream\u0026gt; using namespace std; class Line { public: int getLength(void); Line(int len);\t//简单的构造函数 Line(const Line \u0026amp;obj);\t//拷贝构造函数 ~Line();\t//析构函数 private: int *ptr; }; // 成员函数定义,包括构造函数 Line::Line(int len) { cout \u0026lt;\u0026lt; \u0026#34;调用构造函数\u0026#34; \u0026lt;\u0026lt; endl; // 为指针分配内存 ptr = new int; *ptr = len; } Line::Line(const Line \u0026amp;obj) { cout \u0026lt;\u0026lt; \u0026#34;调用拷贝构造函数并为指针ptr分配内存\u0026#34; \u0026lt;\u0026lt; endl; ptr = new int; *ptr = *obj.ptr;\t//拷贝值 } Line::~Line(void) { cout \u0026lt;\u0026lt; \u0026#34;释放内存\u0026#34; \u0026lt;\u0026lt; endl; delete ptr; } int Line::getLength(void) { return *ptr; } void display(Line obj) { cout \u0026lt;\u0026lt; \u0026#34;line 大小:\u0026#34; \u0026lt;\u0026lt; endl \u0026lt;\u0026lt; obj.getLength() \u0026lt;\u0026lt; endl; } // 程序的主函数 int main() { Line line(10); display(line);\treturn 0; } 友元函数 含义 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。\n虽然友元函数的原型有在类的定义中出现过,但友元函数并不是成员函数。\n友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。\n格式 声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend\n1 2 3 4 5 6 7 8 9 class Box { double width; public: double length; friend void printWidth(Box box); void setWidth(double wid); }; 声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:\n1 friend class ClassTwo; 使用场景 C++友元函数的主要使用场景包括:\n1.实现两个类之间的相互访问 如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。\n2.实现运算符重载 重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。\n3.模板类的访问 当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。\n4.调试和测试类的实现 在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。\n5.避免繁琐的getter/setter方法 友元函数可以直接访问私有数据,避免定义许多getter和setter方法。\n6.状态检查 友元函数可以方便地访问对象的状态,用于调试等目的。\n需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。\n示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include \u0026lt;iostream\u0026gt; using namespace std; class Box { double width; public: friend void printWidth(Box box); void setWidth(double wid); }; void Box::setWidth(double wid) { width = wid; } //注意:printWidth()不是任何类的成员函数 void printWidth(Box box) { /* 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 */ cout \u0026lt;\u0026lt; \u0026#34;Width of box: \u0026#34; \u0026lt;\u0026lt; box.width \u0026lt;\u0026lt; endl; } int main() { Box box; box.setWidth(10.0); printWidth(box); return 0; } C++内联函数 含义 C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。\n对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。\n如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。\n在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。\n优缺点 优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.\n缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。\n结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!\n另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。\n有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要;比如虚函数和递归函数就不会被正常内联。\n通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。\n虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.\n示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include \u0026lt;iostream\u0026gt; using namespace std; inline int Max(int x, int y) { return (x \u0026gt; y) ? x : y; } int main() { cout \u0026lt;\u0026lt; \u0026#34;Max (20,10): \u0026#34; \u0026lt;\u0026lt; Max(20,10) \u0026lt;\u0026lt; endl; cout \u0026lt;\u0026lt; \u0026#34;Max (0,200): \u0026#34; \u0026lt;\u0026lt; Max(0,200) \u0026lt;\u0026lt; endl; cout \u0026lt;\u0026lt; \u0026#34;Max (100,1010): \u0026#34; \u0026lt;\u0026lt; Max(100,1010) \u0026lt;\u0026lt; endl; return 0; } 注意事项 在内联函数中不允许使用循环语句和开关语句 内联函数的定义必须出现在内联函数第一次调用之前 类结构中所在的类说明内部定义的函数是内联函数 C++ this指针 含义 在C++中,this指针是一个特殊指针,它指向当前对象的实例。\n在C++中,每个对象都 能通过 this 指针来访问自己的地址。\nthis 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。\n当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。\n友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。\n实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include \u0026lt;iostream\u0026gt; class MyClass { private: int value; public: void setValue(int value) { this-\u0026gt;value = value; } void printValue() { std::cout \u0026lt;\u0026lt; \u0026#34;Value: \u0026#34; \u0026lt;\u0026lt; this-\u0026gt;value \u0026lt;\u0026lt; std::endl; } }; int main() { MyClass obj; obj.setValue(42); obj.printValue(); return 0; } ","date":"2021-09-19T00:00:00Z","image":"https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover_hub246c27766a20e08922e475827469c08_5066_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/","title":"Cplusplus-基础知识复习"},{"content":"函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。\n一般形式如下:\n\u0026lt;数据类型\u0026gt; \u0026lt;函数名称\u0026gt;(\u0026lt;形式参数说明\u0026gt;)\n函数的参数传递 函数之间的参数传递方式:\n全局变量 复制传递方式 地址传递方式 1.全局变量 全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。\n全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。不建议使用\n2.复制传递 调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。\n形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。\n3.地址传递 按地址传递,实参为变量的地址,而形参为同类型的指针。\n被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include \u0026lt;stdio.h\u0026gt; int str_fun(char *p); int main(int argc, char *argv[]) { char s[] = \u0026#34;welcome2023Jiangxi\u0026#34;; int n; n = str_fun(s); printf(\u0026#34;n=%d %s\\n\u0026#34;, n, s); return 0; } // char *p = n\t我们需要习惯将形参联想等于实参,两端逻辑需要相通 int str_fun(char *p) { int num = 0; while(*p != \u0026#39;\\0\u0026#39;) { if(*p \u0026lt;= \u0026#39;z\u0026#39; \u0026amp;\u0026amp; *p \u0026gt;= \u0026#39;a\u0026#39;) { num++; *p -= \u0026#39; \u0026#39;; } p++; } return num; } 函数的传参\u0026ndash;数组 全局数组传递方式\n复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)\n地址传递方式:实参为数组的指针,形参为同类型的指针变量\n案例一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include \u0026lt;stdio.h\u0026gt; int array_sum(int data[], int n);\t//相当于int array_sum(int *data, int n); int main(int argc, char *argv[]) { int a[] = {5, 9, 10, 3, 10}; int sum = 0; sum = array_sum(a,sizeof(a) / sizeof(int)); printf(\u0026#34;sum=%d\\n\u0026#34;, sum); return 0; } int array_sum(int data[], int n) // int data[] = a;--\u0026gt;error {\tint ret = 0; int i; for(i = 0; i \u0026lt; n; i++) { ret += data[i]; } return ret; } 上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是int data[],此时的int data[]实际就是int *data,使用sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度。\n案例二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // try to write a function,which delete the space character of character string. #include \u0026lt;stdio.h\u0026gt; void del_space(char *str); int main(int argc, char *argv[]) { char a[] = \u0026#34;hello world,hello linux!\u0026#34;; puts(a); del_space(a); puts(a); return 0; } void del_space(char *str) { char *p; p = str; while(*str) { if(*str == \u0026#39; \u0026#39;) { str++; } else { *p = *str; p++; str++; } } *p = \u0026#39;\\0\u0026#39;; } 此处是删除一段字符串中的空格字符,在void del_space()函数中,我们采取的是指针地址传递的形式,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位\\0时,代表字符串的末尾,因此我们也需要为赋值*p = '\\0';代表末位。\n指针函数 1.基本概念 指针函数是指一个函数的返回值为地址量的函数。\n2.定义形式 函数指针的定义的一般形式如下:\n1 2 3 4 5 6 7 \u0026lt;数据类型\u0026gt; * \u0026lt;函数名称\u0026gt;(\u0026lt;参数说明\u0026gt;){ 语句序列; } `返回值:全局变量的地址 / static变量的地址 / 字符串常量的地址 / 堆的地址` 3.示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 // 编写一个指针函数,删除一个字符串中的空格 #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; char *del_space(char *s); int main(int argc, char *argv[]) { char * r; char str[] = \u0026#34;How ar e y ou!\u0026#34;; r = del_space(str); printf(\u0026#34;----%s---\\n\u0026#34;,r); puts(str); return 0; } char *del_space(char *s) { char *p = s; char *r = s; while(*s) { if(*s == \u0026#39; \u0026#39;) { s++; } else { *p = *s; s++; p++; } } *p = \u0026#39;\\0\u0026#39;; return r; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // 编写一个函数,实现两个字符串的连接 #include \u0026lt;stdio.h\u0026gt; char *mstrcat(char *dest, const char * src); int main(int argc, char *argv[]) { char dest[59] = \u0026#34;welcome\u0026#34;; char src[] = \u0026#34;makeru\u0026#34;; puts(mstrcat(dest,src)); puts(dest); return 0; } char *mstrcat(char *dest, const char * src) { char *r = dest; while(*dest) { dest++; } while(*src) { *dest = *src; dest++; src++; } *dest = \u0026#39;\\0\u0026#39;; return r; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 // 编写一个函数,将传入的整型转成字符串 #include \u0026lt;stdio.h\u0026gt; char * itoa(int n); int main(int argc, char *argv[]) { int n; char s[50], *r; printf(\u0026#34;input:\u0026#34;); scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); r = itoa(s, n); puts(r); puts(s); return 0; } char * itoa(char *p, int n) { int r, i = 0, j; //static char p[50]; while(n) { r = n % 10; n /= 10; p[i] = r + \u0026#39;0\u0026#39;; i++; } p[i] = \u0026#39;\\0\u0026#39;; j = i - 1; i = 0; while(i \u0026lt; j) { r = p[i]; p[i] = p[j]; p[j] = r; j--; i++; } return p; } 递归函数 1.基本概念 递归函数是指一个函数的函数体中直接或间接调用了该函数自身\n递归函数调用的执行过程分为两个阶段:\n递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。 回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。 2.示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 计算n! #include \u0026lt;stdio.h\u0026gt; int fac(int n); int main(int argc, char *argv[]) { int n; printf(\u0026#34;input:\u0026#34;); scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); printf(\u0026#34;%d\\n\u0026#34;, fac(n)); return 0; } int fac(int n) { if(n == 0 || n == 1) return 1; return n * fac(n-1); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // 编写一段程序,计算斐波那契序列 #include \u0026lt;stdio.h\u0026gt; int fib(int n); int main(int argc, char *argv[]) { int n = 1; while(n \u0026lt;= 10) { printf(\u0026#34;%d \u0026#34;,fib(n)); n++; } printf(\u0026#34;\\n\u0026#34;); return 0; } int fib(int n) { if(n == 1 || n == 2) return 1; return fib(n-1)+fib(n-2); } 函数指针 1.基本概念 函数指针用来存放函数的地址,这个地址是一个函数的入口地址\n函数名代表了函数的入口地址 2.定义形式 函数指针变量说明的一般形式如下:\n1 2 3 4 \u0026lt;数据类型\u0026gt; (*\u0026lt;函数指针名称\u0026gt;) (\u0026lt;参数说明列表\u0026gt;); eg: int (*p)(int a, int b); 3.函数指针数组 定义:函数指针数组是一个保存若干个函数名的数组。\n一般形式如下:\n1 2 3 4 \u0026lt;数据类型\u0026gt; (*\u0026lt;函数指针数组名称\u0026gt;)(\u0026lt;大小\u0026gt;)(\u0026lt;参数说明列表\u0026gt;); ---\u0026lt;大小\u0026gt;:指函数指针数组元素的个数 ---其他等同普通的函数指针 4.示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 编写一段程序,实现qsort()排序的功能 #include \u0026lt;stdio.h\u0026gt; int compare(const void*, const void *); int main(int argc, char *argv[]) { int s[] = {89, 23, 5, 54, 75}, n, i; n = sizeof(s) / sizeof(int); qsort(s, n, sizeof(int), compare); for(i = 0;i \u0026lt; n; i++) printf(\u0026#34;%d \u0026#34;,s[i]); puts(\u0026#34;\u0026#34;); return 0; } int compare(const void* p, const void *q) { return (*(int *)p - *(int *)q); } ","date":"2021-08-29T00:00:00Z","image":"https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover_hue4c767a73a4c40ef0fc0194b9f009308_62623_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/","title":"C素养提升-函数专题"},{"content":"指针 在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。\n在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。\n地址和变量 在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址。\n编译或函数调用时为其分配内存单元。\n变量是对程序中数据存储空间的抽象。\n指针变量的说明 一般形式如下:\n1 2 3 \u0026lt;存储类型\u0026gt; \u0026lt;数据类型\u0026gt; * \u0026lt;指针变量名\u0026gt;; 例如,char *pName; 指针的存储类型是指针变量本身的存储类型。\n指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。\n指针在说明的同时,也可以被赋值初值,成为指针的初始化\n一般形式如下:\n1 2 3 \u0026lt;存储类型\u0026gt; \u0026lt;数据类型\u0026gt; * \u0026lt;指针变量名\u0026gt; = \u0026lt;地址量\u0026gt;; 例如:int a, *pa = \u0026amp;a; 在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。\n1 2 int a = 3; int *pa = \u0026amp;a;\t//相当于:int * pa; pa = \u0026amp;a; 下面是一个程序示例:\n1 2 3 4 5 6 7 8 9 #include \u0026lt;stdio.h\u0026gt; int main(int argc, char *argv[]) { int a = 10; int * p; p = \u0026amp;a; printf(\u0026#34;p:%p a:%p\\n\u0026#34;,p,\u0026amp;a); return 0; } 可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是0x7fff64003e1c\n下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:\n1 2 3 4 5 6 7 8 9 10 #include \u0026lt;stdio.h\u0026gt; int main(int argc, char *argv[]) { int a = 10; int * p; p = \u0026amp;a; printf(\u0026#34;\u0026amp;p:%p sizeof(p):%d\\n\u0026#34;,\u0026amp;p,sizeof(p)); printf(\u0026#34;p:%p a:%p\\n\u0026#34;,p,\u0026amp;a); return 0; } 编译查看结果,可以发现上述的p = \u0026amp;a是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的0x7ffc915b44e0\n一般我们清楚,在指针中*p是作为取值,而\u0026amp;p则是取地址,我们再次对程序作出修改:\n1 2 3 4 5 6 7 8 9 10 11 #include \u0026lt;stdio.h\u0026gt; int main(int argc, char *argv[]) { int a = 10; int * p; p = \u0026amp;a; printf(\u0026#34;\u0026amp;p:%p sizeof(p):%d\\n\u0026#34;,\u0026amp;p,sizeof(p)); printf(\u0026#34;p:%p a:%p\\n\u0026#34;,p,\u0026amp;a); printf(\u0026#34;%d %p %d \\n\u0026#34;,*p,*(\u0026amp;p),*(*(\u0026amp;p))); return 0; } 那么我们可以看到a = *p = *(*(\u0026amp;p)) = 10,仔细理解*(*(\u0026amp;p)),也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是p = *(\u0026amp;p),此时对其取地址,可以发现和p所对应的地址相同,此时再对*(*(\u0026amp;p))取值,那么也就是对应的一个数据,同理,\u0026amp;p = \u0026amp;(*(\u0026amp;p))也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。\n指针的目标 指针指向的内存区域中的数据成为指针的目标。\n如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。\n在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。\n引入指针 引入指针要注意程序中的px, *px和\u0026amp;px三种表示方法的不同意义。设px为一个指针,则:\npx \u0026mdash; 指针变量,它的内容是地址量\n*px \u0026mdash; 指针所指向的对象,它的内容是数据\n\u0026amp;px \u0026mdash; 指针变量所占用的存储区域的地址,是个常量\n指针的赋值 指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。\n向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)\n指针赋值运算常见的有以下几种形式:\n1 2 3 4 5 6 7 8 9 10 11 12 // 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: double x = 15, *px; px = \u0026amp;x; // 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: float a, *px, *py; px = \u0026amp;a; py = px; // 3、把一个数据的地址赋给具有相同数据类型的指针: int a[20], *pa; pa = a;\t//等价 pa = \u0026amp;a[0] 下面是一个程序案例:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include \u0026lt;stdio.h\u0026gt; int main(int argc, char *argv[]) { int a = 10; int * p; int * q; p = \u0026amp;a; q = \u0026amp;a; printf(\u0026#34;\u0026amp;p:%p %d\\n\u0026#34;,\u0026amp;p,sizeof(p)); printf(\u0026#34;p:%p a:%p\\n\u0026#34;,p,\u0026amp;a); printf(\u0026#34;%d %d\\n\u0026#34;,a,*p); printf(\u0026#34;\\n\\n\u0026amp;q:%p %d\\n\u0026#34;,\u0026amp;q,sizeof(q)); printf(\u0026#34;%p %d\\n\u0026#34;,q,*q); return 0; } 在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,),也就是说指针p和指针q都是指向目标变量a。\n指针运算 指针运算是以指针变量所存放的地址量作为运算量而进行的运算。\n指针运算的实质就是地址的计算。\n指针运算的种类是有限的,它只能进行赋值运算、算术运算和关系运算。\n运算符 计算形式 意 义 + px+n 指针向地址大的方向移动n个数据 - px-n 指针向地址小的方向移动n个数据 ++ px++ 指针向地址小的方向移动1个数据 \u0026ndash; px\u0026ndash; 指针向地址小的方向移动1个数据 - px-py 两个指针之间相隔数据元素的个数 不同数据类型的两个指针实行加减整数运算是无意义的。\npx+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n\npx-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n\npx-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。\n两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。\n指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。\n注意:\n两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误,示例如下:\n正确的运行示例:\n这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数\n下面是一些指针运算的示例:\n上述程序重要的就是理顺指针的关系以及运算符优先级问题。\n知识扩展:\n在32位系统与64位系统下,不同数据类型所对应的字节数\u0026mdash;\u0026gt;\n数据类型 32位 64位 备注 char 1 1 short 2 2 int 4 4 long 4 8 32位与64位不同 float 4 4 char * 4 8 其他指针类型如long *,int *也是如此 long long 8 8 double 8 8 long double 10/12 10/16 有效位10字节。32位为了对其实际分配12字节;64位分配16字节 指针与数组 指针对数组的访问 在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。\n一维数组的数组名为以为数组的指针(起始地址)。\n例如:\n1 double x[8]; 因此,x为x数组的起始地址。\n设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:\nx[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]:访问数组第i+1个数组元素,下面参照示例:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5}; int *p, i, n; p = a; n = sizeof(a) / sizeof(int); printf(\u0026#34;%d\\n\u0026#34;,n); printf(\u0026#34;%p %p %p\\n\u0026#34;,a, a+1, a+2); for(i = 0; i \u0026lt; n; i++) printf(\u0026#34;%d %d %d %d\\n\u0026#34;,a[i],*(p+i),*(a+i),p[i]); puts(\u0026#34;\u0026#34;); return 0; } 那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。\n注意:\n指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量\n但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量\n程序案例 程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5}; int *p, *q, t; int n = sizeof(a) / sizeof(int); p = a; q = \u0026amp;a[n-1]; while(p \u0026lt; q) { t =*p; *p = *q; *q = t; p++; q--; } for(t = 0;t \u0026lt; n;t++) { printf(\u0026#34;%d \u0026#34;,a[t]); } puts(\u0026#34;\u0026#34;); return 0; } 程序2\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[] = {4, 6, 2, 8, 9,4, 7, 1, 5}; int *p, i, n; p = a; n = sizeof(a) / sizeof(int); printf(\u0026#34;%d\\n\u0026#34;,n); printf(\u0026#34;%p %p %p\\n\u0026#34;,a, a+1, a+2); for(i = 0; i \u0026lt; n; i++) printf(\u0026#34;%d %d %d %d\\n\u0026#34;,a[i],*(p+i),*(a+i),p[i]); puts(\u0026#34;\u0026#34;); p++; printf(\u0026#34;%d\\n\u0026#34;,p[1]); return 0; } 这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2\n知识点:\n数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)\n指针与二维数组 二维数组的性质 多维数组就是具有两个或两个以上下标的数组。\n在c语言中,二维数组的元素连续存储,按行优先存取。\n下面看程序案例:\n案例一:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[3][2] = {{1, 6}, {9, 12}, {61, 12}}; int *p, i, n; n = sizeof(a) / sizeof(int); printf(\u0026#34;%d\\n\u0026#34;,n); p = a[0]; printf(\u0026#34;%d\\n\u0026#34;,sizeof(a[0])); printf(\u0026#34;%p %p\\n\u0026#34;, p, p+1); printf(\u0026#34;%p %p\\n\u0026#34;, a, a+1); for(i = 0;i \u0026lt; n; i++) printf(\u0026#34;%d \u0026#34;, *(p+i)); puts(\u0026#34;\u0026#34;); return 0; } 上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。\n案例二:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[3][2] = {{1, 6}, {9, 12}, {61, 12}}; int *p, i, n; n = sizeof(a) / sizeof(int); printf(\u0026#34;%p %p\\n\u0026#34;, a, a+1); printf(\u0026#34;%p %p\\n\u0026#34;, a[0], a[0]+1); printf(\u0026#34;%p %p\\n\u0026#34;, *a, *a+1); return 0; } 从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。\n行指针(数组指针) 二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址\n**存储行地址的指针变量,叫做行指针变量。**形式如下:\n\u0026lt;存储类型\u0026gt; \u0026lt;数据类型\u0026gt; (*\u0026lt;指针变量名\u0026gt;)[表达式];\n例如:int a[2] [3];\tint (*p)[3]\n注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。\n我们用一个程序案例来解释:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[3][2] = {{1, 6}, {9, 12}, {61, 12}}; int (*p)[2]; p = a; printf(\u0026#34;%p %p\\n\u0026#34;,a ,a+1); printf(\u0026#34;%p %p\\n\u0026#34;,p ,p+1); printf(\u0026#34;%d, %d, %d, %d\\n\u0026#34;,a[1][1], p[1][1], *(*(a+1)), *(*((p+1)+1))); printf(\u0026#34;%d %d\\n\u0026#34;,*(*(a+1)),*(*((a+1)+1))); printf(\u0026#34;%p %p\\n\u0026#34;,\u0026amp;(*(a+1)),\u0026amp;(*((a+1)+1))); return 0; } 根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作\u0026amp;,代表的就是取地址【\u0026amp;( *(a+1))】。\n字符指针与字符串 字符指针的定义 C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。\n字符指针的初始化 **初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。\n1 2 char str[] = \u0026#34;Hell World\u0026#34;; char *p = str; 在C编程中,当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。\n1 2 char *p = \u0026#34;Hello World\u0026#34;;\t//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 *p = \u0026#39;h\u0026#39;;\t//错误,字符串常量不能修改 程序案例 1 2 3 4 5 6 7 8 9 10 11 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { char *p1 = \u0026#34;hello world!\u0026#34;; char *p2 = \u0026#34;hello world!\u0026#34;; printf(\u0026#34;\u0026amp;p1=%p %p %s\\n\u0026#34;, \u0026amp;p1, p1, p1); printf(\u0026#34;\u0026amp;p2=%p %p %s\\n\u0026#34;, \u0026amp;p2, p2, p2); return 0; } 此处我们可以看到,由于字符指针的内容都是hello world!,也就是申请了一段字符串空间存取的内容为hello world!,当我们打印字符指针p1和p2指向的地址时可以发现都指向了0x4006a4,接着我们打印指针存放的地址,可以发现\u0026amp;p1=0x7ffc8d801cd8、\u0026amp;p2=0x7ffc8d801ce0,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)**\n指针数组 指针数组的定义 所谓指针数组是指若干个具有相同存储类型和数据类型的指针变量构成的集合。\n指针数组的一般说明形式:\n\u0026lt;存储类型\u0026gt; \u0026lt;数据类型\u0026gt; *\u0026lt;指针数组名\u0026gt;[\u0026lt;大小\u0026gt;];\n指针数组名表示该指针数组的起始地址\n指针数组的声明 声明一个指针数组:\n1 double *pa[2], a[2][3]; 把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:\n1 2 3 4 pa[0] = a[0];\t//等价pa[0] = \u0026amp;a[0][0] pa[1] = a[1];\t//等价pa[1] = \u0026amp;a[1][0] //此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] 程序案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int *p[3]; int a[] = {3, 6, 1, 7, 10}; p[0] = a; p[1] = a + 1; p[2] = a + 3; printf(\u0026#34;%d %d %d\\n\u0026#34;,a[0], a[1], a[3]); printf(\u0026#34;%d %d %d\\n\u0026#34;,*(p[0]),*(p[1]),*(p[2])); printf(\u0026#34;%p %p\\n\u0026#34;,p[0],p[1]); printf(\u0026#34;%p %p\\n\u0026#34;,\u0026amp;p[0],\u0026amp;p[1]); return 0; } 问:指针数组名相当于什么样的指针?\t答:二级指针。\n多级指针 多级指针的定义 把一个指向指针变量的指针变量,称为多级指针。\n对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。\n对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。\n二级指针变量的说明形式如下:\n\u0026lt;存储类型\u0026gt; \u0026lt;数据类型\u0026gt; **\u0026lt;指针名\u0026gt;;\n多级指针的运算 **指针变量加1,是向地址大的方向移动一个目标数据。**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。\n比如:int **p; p+1移动一个int *变量所占的内存空间。\n程序案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[] = {3, 6, 9}; int *p[2] = {\u0026amp;a[0],\u0026amp;a[1]}; int **q; q = \u0026amp;p[0]; q = p; printf(\u0026#34;%d %d\\n\u0026#34;,a[0],a[1]); printf(\u0026#34;%d %d\\n\u0026#34;,*p[0],*p[1]); printf(\u0026#34;%d %d %d\\n\u0026#34;,a[0],*p[0],**q); return 0; } 1 2 3 4 5 6 7 8 9 10 11 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { char *s[] = {\u0026#34;apple\u0026#34;, \u0026#34;pear\u0026#34;, \u0026#34;potato\u0026#34;}; int i, n; n = sizeof(s) / sizeof(char *); printf(\u0026#34;%d %d %d\\n\u0026#34;,n,sizeof(s),sizeof(char *)); return 0; } void指针 void指针的定义 void指针是一种不能确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量。\n一般形式为:\nvoid * \u0026lt;指针变量名\u0026gt;\n对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。\n程序案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int m = 10; double n = 3.14; void *p, *q; p = \u0026amp;m; //(void *) \u0026amp;m printf(\u0026#34;%d %d\\n\u0026#34;,m,*(int *)p); q = \u0026amp;n; //(void *)\u0026amp;n printf(\u0026#34;%.2lf %.2lf\\n\u0026#34;,n, *(double *)q); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include \u0026lt;stdio.h\u0026gt; int main(int argc,char *argv[]) { int a[] = {6, 3, 2, 7, 9, 6}; int i, n; void *p; p = a; n = sizeof(a) / sizeof(int); for(i = 0;i \u0026lt; n;i++) printf(\u0026#34;%d \u0026#34;,*((int *)p +i)); puts(\u0026#34;\u0026#34;); return 0; } 此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要(int *)p进行强转,之后对于用户的算数运算就没什么问题了。\nconst修饰指针 常量化指针目标表达式 一般说明形式如下:\nconst \u0026lt;数据类型\u0026gt; * \u0026lt;指针变量名\u0026gt;[= \u0026lt;指针运算表达式\u0026gt;]\n常量化指针目标是限制通过指针改变其目标的数值,但\u0026lt;指针变量\u0026gt; ---\u0026gt;存储的地址值可以修改。\n常量化指针变量 一般说明形式如下:\n\u0026lt;数据类型\u0026gt; * const \u0026lt;指针变量名\u0026gt;[= \u0026lt;指针运算表达式\u0026gt;]\n使得\u0026lt;指针变量\u0026gt;存储的地址值不能修改。但可以通过* \u0026lt;指针变量名\u0026gt;可以修改指针所指向变量的数值。\n常量化指针变量及目标表达式 一般说明形式如下:\nconst \u0026lt;数据类型\u0026gt; * const \u0026lt;指针变量名\u0026gt;[= \u0026lt;指针运算表达式\u0026gt;]\n常量化指针变量及目标表达式,使得既不可以修改\u0026lt;指针变量名\u0026gt;的地址,也不可以通过* \u0026lt;指针变量名\u0026gt;修改指针所指向变量的值。\n","date":"2021-06-29T00:00:00Z","image":"https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover_hu70b9966484078ba6992d2596edd97753_49429_120x120_fill_q75_box_smart1.jpg","permalink":"https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/","title":"C素养提升-指针专题"}] \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..866d95cc7 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1 @@ +https://kurisaw.github.io/2024-02-18T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/2024-02-18T00:00:00+00:00https://kurisaw.github.io/categories/2024-02-18T00:00:00+00:00https://kurisaw.github.io/post/2024-02-18T00:00:00+00:00https://kurisaw.github.io/tags/rt-thread/2024-02-18T00:00:00+00:00https://kurisaw.github.io/categories/rt-thread/2024-02-18T00:00:00+00:00https://kurisaw.github.io/tags/rtduino/2024-02-18T00:00:00+00:00https://kurisaw.github.io/tags/2024-02-18T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/2024-02-03T15:00:00+00:00https://kurisaw.github.io/tags/experience-sharing/2024-02-03T15:00:00+00:00https://kurisaw.github.io/categories/experience_sharing/2024-02-03T15:00:00+00:00https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/2023-11-04T00:00:00+00:00https://kurisaw.github.io/tags/mcu/2023-11-04T00:00:00+00:00https://kurisaw.github.io/tags/mpu/2023-11-04T00:00:00+00:00https://kurisaw.github.io/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/2023-11-04T00:00:00+00:00https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/2023-10-26T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/2023-10-26T00:00:00+00:00https://kurisaw.github.io/tags/micro_ros/2023-10-26T00:00:00+00:00https://kurisaw.github.io/categories/micro_ros/2023-10-26T00:00:00+00:00https://kurisaw.github.io/tags/ros2/2023-10-26T00:00:00+00:00https://kurisaw.github.io/tags/usb/2023-10-26T00:00:00+00:00https://kurisaw.github.io/tags/wsl/2023-10-26T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/2023-10-09T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/2023-10-09T00:00:00+00:00https://kurisaw.github.io/tags/ci/2023-10-09T00:00:00+00:00https://kurisaw.github.io/tags/git/2023-10-09T00:00:00+00:00https://kurisaw.github.io/categories/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/2023-10-09T00:00:00+00:00https://kurisaw.github.io/tags/linux/2023-10-09T00:00:00+00:00https://kurisaw.github.io/categories/linux/2023-10-09T00:00:00+00:00https://kurisaw.github.io/tags/scripy/2023-10-09T00:00:00+00:00https://kurisaw.github.io/tags/ubuntu/2023-10-09T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/2023-09-16T00:00:00+00:00https://kurisaw.github.io/tags/ssh/2023-09-16T00:00:00+00:00https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/2023-08-20T00:00:00+00:00https://kurisaw.github.io/tags/matter/2023-08-20T00:00:00+00:00https://kurisaw.github.io/categories/matter/2023-08-20T00:00:00+00:00https://kurisaw.github.io/tags/platform/2023-08-20T00:00:00+00:00https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/2023-06-19T00:00:00+00:00https://kurisaw.github.io/tags/esp-c3/2023-06-19T00:00:00+00:00https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/2023-06-14T00:00:00+00:00https://kurisaw.github.io/tags/csa/2023-06-14T00:00:00+00:00https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/2023-06-07T00:00:00+00:00https://kurisaw.github.io/tags/ble/2023-06-07T00:00:00+00:00https://kurisaw.github.io/tags/nordic/2023-06-07T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/2023-05-31T00:00:00+00:00https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/2023-05-30T00:00:00+00:00https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/2023-05-24T00:00:00+00:00https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/2023-05-06T00:00:00+00:00https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/2023-05-04T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/2023-05-04T00:00:00+00:00https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/easyflash/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/fal/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/lpc/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/lpc55s69/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/nxp/2023-04-23T00:00:00+00:00https://kurisaw.github.io/categories/nxp%E5%AD%A6%E4%B9%A0/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/sfud/2023-04-23T00:00:00+00:00https://kurisaw.github.io/tags/bsd/2023-04-12T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/2023-04-12T00:00:00+00:00https://kurisaw.github.io/tags/sal%E5%A5%97%E6%8E%A5%E5%AD%97/2023-04-12T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/2023-04-11T00:00:00+00:00https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/2023-04-10T00:00:00+00:00https://kurisaw.github.io/tags/tcp/ip/2023-04-10T00:00:00+00:00https://kurisaw.github.io/tags/udp/2023-04-10T00:00:00+00:00https://kurisaw.github.io/tags/wireshark/2023-04-10T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/2023-04-10T00:00:00+00:00https://kurisaw.github.io/categories/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/2023-04-10T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/2023-04-09T00:00:00+00:00https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/2023-04-07T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/2023-04-07T00:00:00+00:00https://kurisaw.github.io/tags/bearpi-hm_micro/2023-04-07T00:00:00+00:00https://kurisaw.github.io/tags/harmonyos/2023-04-07T00:00:00+00:00https://kurisaw.github.io/categories/harmonyos/2023-04-07T00:00:00+00:00https://kurisaw.github.io/tags/sftp/2023-04-07T00:00:00+00:00https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/2023-04-03T00:00:00+00:00https://kurisaw.github.io/tags/%E8%B5%84%E8%AE%AF/2023-04-03T00:00:00+00:00https://kurisaw.github.io/categories/%E8%B5%84%E8%AE%AF/2023-04-03T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/2023-03-29T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/2023-03-17T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/kmp/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/leetcode/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/2023-03-13T00:00:00+00:00https://kurisaw.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/2023-03-13T00:00:00+00:00https://kurisaw.github.io/tags/%E7%AE%97%E6%B3%95/2023-03-13T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/2023-02-22T00:00:00+00:00https://kurisaw.github.io/tags/%E5%89%91%E6%8C%87offer/2023-02-22T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/2023-02-21T00:00:00+00:00https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/2023-02-21T00:00:00+00:00https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A7%A3%E6%B3%95/2023-02-21T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/2023-02-20T00:00:00+00:00https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E5%87%BD%E6%95%B0/2023-02-20T00:00:00+00:00https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E7%A2%B0%E6%92%9E/2023-02-20T00:00:00+00:00https://kurisaw.github.io/tags/%E7%BA%BF%E6%80%A7%E6%8E%A2%E6%B5%8B%E6%B3%95/2023-02-20T00:00:00+00:00https://kurisaw.github.io/tags/%E9%93%BE%E5%9C%B0%E5%9D%80%E6%B3%95/2023-02-20T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/2023-02-18T00:00:00+00:00https://kurisaw.github.io/tags/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/2023-02-18T00:00:00+00:00https://kurisaw.github.io/tags/%E9%93%BE%E8%A1%A8/2023-02-18T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/2023-02-17T00:00:00+00:00https://kurisaw.github.io/tags/%E9%80%92%E5%BD%92%E6%B3%95/2023-02-17T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/2023-02-16T00:00:00+00:00https://kurisaw.github.io/tags/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/2023-02-16T00:00:00+00:00https://kurisaw.github.io/tags/%E6%95%B0%E7%BB%84/2023-02-16T00:00:00+00:00https://kurisaw.github.io/tags/%E6%9A%B4%E5%8A%9B%E8%A7%A3%E6%B3%95/2023-02-16T00:00:00+00:00https://kurisaw.github.io/tags/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/2023-02-16T00:00:00+00:00https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/2023-02-15T00:00:00+00:00https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/2023-02-06T00:00:00+00:00https://kurisaw.github.io/tags/micropython/2023-02-06T00:00:00+00:00https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/2023-02-05T00:00:00+00:00https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/2023-02-04T00:00:00+00:00https://kurisaw.github.io/tags/d1s/2023-01-19T00:00:00+00:00https://kurisaw.github.io/tags/rdc/2023-01-19T00:00:00+00:00https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/2023-01-19T00:00:00+00:00https://kurisaw.github.io/tags/risc-v/2023-01-19T00:00:00+00:00https://kurisaw.github.io/tags/rt-smart/2023-01-19T00:00:00+00:00https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/2022-08-22T00:00:00+00:00https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/2022-07-29T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/2022-07-28T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/2022-07-25T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/2022-07-24T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/2022-07-24T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/2022-07-23T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/2022-07-22T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/2022-07-22T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/2022-07-22T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/2022-07-17T00:00:00+00:00https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/2022-07-16T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/2022-07-16T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/2022-07-15T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/2022-07-15T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/2022-07-14T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/2022-07-14T00:00:00+00:00https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/2022-07-14T00:00:00+00:00https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-07-14T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/2022-07-13T00:00:00+00:00https://kurisaw.github.io/tags/env/2022-05-12T00:00:00+00:00https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/2022-05-12T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/2022-04-12T00:00:00+00:00https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/2022-03-30T00:00:00+00:00https://kurisaw.github.io/tags/operating-system/2022-03-22T00:00:00+00:00https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/2022-03-22T00:00:00+00:00https://kurisaw.github.io/categories/operating_system/2022-03-10T00:00:00+00:00https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/2022-03-10T00:00:00+00:00https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/2022-03-08T00:00:00+00:00https://kurisaw.github.io/archives/2022-03-06T00:00:00+00:00https://kurisaw.github.io/page/2022-03-06T00:00:00+00:00https://kurisaw.github.io/tags/cplusplus/2021-09-19T00:00:00+00:00https://kurisaw.github.io/categories/cplusplus/2021-09-19T00:00:00+00:00https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/%E5%A4%9A%E6%80%81%E6%80%A7/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/%E5%B0%81%E8%A3%85%E6%80%A7/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/%E6%8A%BD%E8%B1%A1%E6%80%A7/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/%E7%BB%A7%E6%89%BF%E6%80%A7/2021-09-19T00:00:00+00:00https://kurisaw.github.io/tags/c_pointer/2021-08-29T00:00:00+00:00https://kurisaw.github.io/categories/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87/2021-08-29T00:00:00+00:00https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/2021-08-29T00:00:00+00:00https://kurisaw.github.io/tags/c%E8%AF%AD%E8%A8%80/2021-08-29T00:00:00+00:00https://kurisaw.github.io/tags/%E5%87%BD%E6%95%B0/2021-08-29T00:00:00+00:00https://kurisaw.github.io/tags/%E6%8C%87%E9%92%88/2021-08-29T00:00:00+00:00https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/2021-06-29T00:00:00+00:00https://kurisaw.github.io/about/https://kurisaw.github.io/documents/https://kurisaw.github.io/explore/https://kurisaw.github.io/links/https://kurisaw.github.io/quote/https://kurisaw.github.io/search/ \ No newline at end of file diff --git a/tags/bearpi-hm_micro/index.html b/tags/bearpi-hm_micro/index.html new file mode 100644 index 000000000..bd9a83f48 --- /dev/null +++ b/tags/bearpi-hm_micro/index.html @@ -0,0 +1,55 @@ +Tag: BearPi-HM_Micro - kurisaW +

Tags

1 page

BearPi-HM_Micro

\ No newline at end of file diff --git a/tags/bearpi-hm_micro/index.xml b/tags/bearpi-hm_micro/index.xml new file mode 100644 index 000000000..809040d79 --- /dev/null +++ b/tags/bearpi-hm_micro/index.xml @@ -0,0 +1,306 @@ +BearPi-HM_Micro on kurisaWhttps://kurisaw.github.io/tags/bearpi-hm_micro/Recent content in BearPi-HM_Micro on kurisaWHugo -- gohugo.ioenFri, 07 Apr 2023 00:00:00 +0000【HarmonyOS】小熊派鸿蒙系统搭建https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建" /><h2 id="一bearpi-hm-micro-开发板介绍">一、BearPi-HM Micro 开发板介绍 +</h2><p>BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。</p> +<h2 id="二linux镜像下载">二、Linux镜像下载 +</h2><p>下载官方提供镜像(任选一种方式下载)</p> +<ul> +<li>Ubuntu20.04(大小8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1W0cgtXC5T2bv0lAya7eizA" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA</a> 提取码:1234</li> +<li>Ubuntu18.04(大小4.8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1YIdqlRWRGq_heAfrgQ7EPQ" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ</a> 提取码:1234</li> +</ul> +<h2 id="三bearpi-hm-micro编译环境配置">三、BearPi-HM Micro编译环境配置 +</h2><p>在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置</p> +<h4 id="1首先添加如下镜像源">1.首先添加如下镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /etc/apt/source.list +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 添加中科大源 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2更新镜像源">2.更新镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get update +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3安装依赖库及工具">3.安装依赖库及工具 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">gcc</span> <span class="n">g</span><span class="o">++</span> <span class="n">make</span> <span class="n">zlib</span><span class="o">*</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">e2fsprogs</span> <span class="n">pkg</span><span class="o">-</span><span class="n">config</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">perl</span> <span class="n">bc</span> <span class="n">openssl</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">libelf</span><span class="o">-</span><span class="n">dev</span> <span class="n">libc6</span><span class="o">-</span><span class="n">dev</span><span class="o">-</span><span class="n">amd64</span> <span class="n">binutils</span> <span class="n">binutils</span><span class="o">-</span><span class="n">dev</span> <span class="n">libdwarf</span><span class="o">-</span><span class="n">dev</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">tools</span> <span class="n">mtd</span><span class="o">-</span><span class="n">utils</span> <span class="n">gcc</span><span class="o">-</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabi</span> <span class="n">cpio</span> <span class="n">device</span><span class="o">-</span><span class="n">tree</span><span class="o">-</span><span class="n">compiler</span> <span class="n">net</span><span class="o">-</span><span class="n">tools</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> <span class="n">git</span> <span class="n">vim</span> <span class="n">openjdk</span><span class="o">-</span><span class="mi">11</span><span class="o">-</span><span class="n">jre</span><span class="o">-</span><span class="n">headless</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装hb">4.安装hb +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 安装hb命令 +</span></span><span class="line"><span class="cl">python3 -m pip install --user ohos-build==0.4.3 +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 环境变量配置</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 在.bashrc文件最后一行添加如下代码,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/.</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5测试hb是否安装成功">5.测试hb是否安装成功 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb -h +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071818214.png" +loading="lazy" +alt="image-20230407181805793" +></p> +<h2 id="四安装mkimage工具">四、安装mkimage工具 +</h2><p>首先解释这个工具的用途:<strong>用来制作不压缩或者压缩的多种可启动映象文件。</strong></p> +<h4 id="1新建tools目录">1.新建tools目录 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">~/</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2下载mkimagestm32工具到tools目录并复制到homebearpitools目录下">2.下载mkimage.stm32工具到<code>~/tools</code>目录,并复制到/home/bearpi/tools/目录下 +</h4><ul> +<li><a class="link" href="https://pan.baidu.com/share/init?surl=T2O8luJ0-8g5ZZYdOvWfqQ" target="_blank" rel="noopener" +>mkimage.stm32下载地址</a> 提取码:1234</li> +</ul> +<h4 id="3修改mkimagestm32文件权限">3.修改mkimage.stm32文件权限 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chmod</span> <span class="mi">777</span> <span class="o">~/</span><span class="n">tools</span><span class="o">/</span><span class="n">mkimage</span><span class="o">.</span><span class="n">stm32</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4设置环境变量">4.设置环境变量 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 将下面的代码拷贝至.bashrc文件最后,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/</span><span class="n">tools</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="五bearpi镜像导入vmware">五、bearpi镜像导入VMware +</h2><p>准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-&gt;打开(O),选择我们Linux镜像中的<code>BearPi-HM_Micro_Ubuntu.ovf</code>文件,等待镜像文件的导入,开始登录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">账户:bearpi +</span></span><span class="line"><span class="cl">密码:bearpi +</span></span></code></pre></td></tr></table> +</div> +</div><p>首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-&gt;设置-&gt;网络适配器-&gt;NAT模式</p> +<p>此时打开一个终端,输入ifconfig查看ip</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071852103.png" +loading="lazy" +alt="image-20230407185206621" +></p> +<h2 id="六源码获取">六、源码获取 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mkdir project &amp;&amp; cd project +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七编译代码">七、编译代码 +</h2><p>首先进入到项目文件夹中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi/project/bearpi-hm_micro_small/ +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行如下命令(普通用户模式终端下):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb set +</span></span></code></pre></td></tr></table> +</div> +</div><p>出现<code>[OHOS INFO] Input code path: </code>提示信息后再输入<code>.</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071902001.png" +loading="lazy" +alt="image-20230407190200859" +></p> +<p>我们选择<code>bearpi-hm_micro</code>后回车</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071904137.png" +loading="lazy" +alt="image-20230407190426957" +></p> +<p>输入下面的命令,等待下载程序完成</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb build -t notest --tee -f +</span></span></code></pre></td></tr></table> +</div> +</div><p>当出现<code>build success</code>时,即代表编译成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071916323.png" +loading="lazy" +alt="image-20230407191628183" +></p> +<h2 id="八查看编译出的固件位置">八、查看编译出的固件位置 +</h2><p>当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: <code>/home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro</code> 其中有以下文件是后面烧录系统需要使用的。</p> +<ul> +<li>OHOS_Image.stm32:系统镜像文件</li> +<li>rootfs_vfat.img:根文件系统</li> +<li>userfs_vfat.img:用户文件系统</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071919790.png" +loading="lazy" +alt="image-20230407191938678" +></p> +<p>我们将这三个文件复制到该目录下:<code>/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/</code>,方便后续烧录系统使用</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="n">OHOS_Image</span><span class="o">.</span><span class="n">stm32</span> <span class="n">rootfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="n">userfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">bearpi</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">bearpi</span><span class="o">-</span><span class="n">hm_micro_small</span><span class="o">/</span><span class="n">applications</span><span class="o">/</span><span class="n">BearPi</span><span class="o">/</span><span class="n">BearPi</span><span class="o">-</span><span class="n">HM_Micro</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">download_img</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071929824.png" +loading="lazy" +alt="image-20230407192926584" +></p> +<h2 id="九固件烧录">九、固件烧录 +</h2><h4 id="1准备工作">1.准备工作 +</h4><ul> +<li><a class="link" href="https://www.wch.cn/downloads/CH341SER_EXE.html" target="_blank" rel="noopener" +>CH340驱动</a></li> +<li><a class="link" href="https://www.st.com/en/development-tools/stm32cubeprog.html#get-software" target="_blank" rel="noopener" +>STM32CubeProgramme(v2.4.0+)</a></li> +</ul> +<h4 id="2连接开发板">2.连接开发板 +</h4><p>首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:<a class="link" href="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/" target="_blank" rel="noopener" +>【Linux系统开发】Ubuntu配置SFTP服务</a>)</p> +<p>当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。</p> +<p>我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111834424.png" +loading="lazy" +alt="image-20230411183456029" +></p> +<h4 id="3镜像烧录">3.镜像烧录 +</h4><ul> +<li> +<p>首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。</p> +</li> +<li> +<p>打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。</p> +</li> +<li> +<p>点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:<code>Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv</code>)。</p> +</li> +<li> +<p>点击Browse按钮,然后选择工程源码下的烧录镜像路径</p> +</li> +<li> +<p>点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111935608.png" +loading="lazy" +alt="image-20230411193521444" +></p> +<h4 id="4启动系统">4.启动系统 +</h4><p>将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111940183.jpg" +loading="lazy" +alt="3" +></p> \ No newline at end of file diff --git a/tags/bearpi-hm_micro/page/1/index.html b/tags/bearpi-hm_micro/page/1/index.html new file mode 100644 index 000000000..700e4854d --- /dev/null +++ b/tags/bearpi-hm_micro/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/bearpi-hm_micro/ + \ No newline at end of file diff --git a/tags/ble/index.html b/tags/ble/index.html new file mode 100644 index 000000000..534e6d77b --- /dev/null +++ b/tags/ble/index.html @@ -0,0 +1,55 @@ +Tag: BLE - kurisaW +

Tags

2 pages

BLE

\ No newline at end of file diff --git a/tags/ble/index.xml b/tags/ble/index.xml new file mode 100644 index 000000000..021d5b230 --- /dev/null +++ b/tags/ble/index.xml @@ -0,0 +1,789 @@ +BLE on kurisaWhttps://kurisaw.github.io/tags/ble/Recent content in BLE on kurisaWHugo -- gohugo.ioenWed, 07 Jun 2023 00:00:00 +0000【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul> \ No newline at end of file diff --git a/tags/ble/page/1/index.html b/tags/ble/page/1/index.html new file mode 100644 index 000000000..8c5077baa --- /dev/null +++ b/tags/ble/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ble/ + \ No newline at end of file diff --git a/tags/bsd/index.html b/tags/bsd/index.html new file mode 100644 index 000000000..031616ef7 --- /dev/null +++ b/tags/bsd/index.html @@ -0,0 +1,55 @@ +Tag: BSD - kurisaW +

Tags

1 page

BSD

\ No newline at end of file diff --git a/tags/bsd/index.xml b/tags/bsd/index.xml new file mode 100644 index 000000000..994738ae2 --- /dev/null +++ b/tags/bsd/index.xml @@ -0,0 +1,830 @@ +BSD on kurisaWhttps://kurisaw.github.io/tags/bsd/Recent content in BSD on kurisaWHugo -- gohugo.ioenWed, 12 Apr 2023 00:00:00 +0000RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div> \ No newline at end of file diff --git a/tags/bsd/page/1/index.html b/tags/bsd/page/1/index.html new file mode 100644 index 000000000..0b6cf0b23 --- /dev/null +++ b/tags/bsd/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/bsd/ + \ No newline at end of file diff --git a/tags/c_pointer/index.html b/tags/c_pointer/index.html new file mode 100644 index 000000000..505bb71f6 --- /dev/null +++ b/tags/c_pointer/index.html @@ -0,0 +1,55 @@ +Tag: C_pointer - kurisaW +

Tags

2 pages

C_pointer

\ No newline at end of file diff --git a/tags/c_pointer/index.xml b/tags/c_pointer/index.xml new file mode 100644 index 000000000..82cfb6946 --- /dev/null +++ b/tags/c_pointer/index.xml @@ -0,0 +1,1843 @@ +C_pointer on kurisaWhttps://kurisaw.github.io/tags/c_pointer/Recent content in C_pointer on kurisaWHugo -- gohugo.ioenSun, 29 Aug 2021 00:00:00 +0000C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p> \ No newline at end of file diff --git a/tags/c_pointer/page/1/index.html b/tags/c_pointer/page/1/index.html new file mode 100644 index 000000000..6860336b9 --- /dev/null +++ b/tags/c_pointer/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/c_pointer/ + \ No newline at end of file diff --git a/tags/ci/index.html b/tags/ci/index.html new file mode 100644 index 000000000..5eb79ddd3 --- /dev/null +++ b/tags/ci/index.html @@ -0,0 +1,55 @@ +Tag: CI - kurisaW +

Tags

3 pages

CI

\ No newline at end of file diff --git a/tags/ci/index.xml b/tags/ci/index.xml new file mode 100644 index 000000000..d8409023b --- /dev/null +++ b/tags/ci/index.xml @@ -0,0 +1,520 @@ +CI on kurisaWhttps://kurisaw.github.io/tags/ci/Recent content in CI on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p>Github同步Gitee镜像仓库自动化脚本https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/Tue, 11 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover.jpg" alt="Featured image of post Github同步Gitee镜像仓库自动化脚本" /><h1 id="github同步gitee镜像仓库自动化脚本">Github同步Gitee镜像仓库自动化脚本 +</h1><hr> +<h2 id="前言">前言 +</h2><p>在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。</p> +<h2 id="什么是hub-mirror-action">什么是Hub Mirror Action? +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111537579.png" +loading="lazy" +alt="image-20230411153729450" +></p> +<h3 id="1介绍">1.介绍 +</h3><p><a class="link" href="https://github.com/marketplace/actions/hub-mirror-action" target="_blank" rel="noopener" +>Hub Mirror Action</a>是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。</p> +<h3 id="2用法">2.用法 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Mirror the Github organization repos to Gitee.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># src_account_type: org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># dst_account_type: org</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:详细使用案例请查看官方仓库 <a class="link" href="https://github.com/Yikun/hub-mirror-action" target="_blank" rel="noopener" +>https://github.com/Yikun/hub-mirror-action</a></p> +<h2 id="配置步骤">配置步骤 +</h2><h3 id="1生成密钥对">1.生成密钥对 +</h3><p>我们先在本地使用git命令行打开终端,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ssh</span><span class="o">-</span><span class="n">keygen</span> <span class="o">-</span><span class="n">t</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">f</span> <span class="o">~/</span><span class="n">Documents</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">key</span><span class="o">/</span><span class="n">id_rsa</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注:请确保文件夹<code>~/Documents/ssh-key/</code>存在,当然你也可以选择放置在其他地方</p> +<p>过程中一路回车即可,注意不要设置密码。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111543237.png" +loading="lazy" +alt="image-20230411154330166" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111551053.png" +loading="lazy" +alt="image-20230411155124878" +></p> +<h3 id="2github私钥配置">2.GitHub私钥配置 +</h3><p>首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111547966.png" +loading="lazy" +alt="image-20230411154716849" +></p> +<ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_PRIVATE_KEY</code>的secret,值为我们之前生成的密钥对中的私钥(id_rsa)</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111553202.png" +loading="lazy" +alt="image-20230411155314101" +></p> +<h3 id="3gitee公钥配置">3.Gitee公钥配置 +</h3><p>我们打开Gitee账号,进入<code>Settings-&gt;安全设置-&gt;SSH公钥</code></p> +<p>添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111558684.png" +loading="lazy" +alt="image-20230411155846562" +></p> +<h3 id="4gitee生成私人令牌">4.Gitee生成私人令牌 +</h3><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111559999.png" +loading="lazy" +alt="image-20230411155958898" +></p> +<p>令牌名称随意,同时复制生成的令牌值。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111601466.png" +loading="lazy" +alt="image-20230411160127393" +></p> +<h3 id="5github绑定gitee令牌">5.Github绑定Gitee令牌 +</h3><ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_TOKEN</code>的secret,值为Gitee生成的令牌值</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111603849.png" +loading="lazy" +alt="image-20230411160340721" +></p> +<h3 id="6编写ci脚本">6.编写CI脚本 +</h3><p>将<code>ci_bot</code>仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="n">ci_bot</span><span class="o">/</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="p">.</span><span class="n">github</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">workflows</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">Sync</span><span class="p">.</span><span class="n">yml</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>Sync.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">push, delete, create ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出后,将本次修改push到远端仓库。</p> +<p>查看Action运行情况:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111611887.png" +loading="lazy" +alt="image-20230411161143741" +></p> +<h3 id="7多仓库同步推送">7.多仓库同步推送 +</h3><p>如果你想同时同步多个仓库,只需要完成如下修改</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">static_list 默认为&#39;&#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111633375.png" +loading="lazy" +alt="image-20230411163307283" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111631352.png" +loading="lazy" +alt="image-20230411163135259" +></p> +<h3 id="8定时运行脚本">8.定时运行脚本 +</h3><p>为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:</p> +<p>修改Sync.yml文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 0 * * *&#39;</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">delete</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">create</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111731377.png" +loading="lazy" +alt="image-20230411173142865" +></p> +<h2 id="总结">总结 +</h2><p>通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。</p> \ No newline at end of file diff --git a/tags/ci/page/1/index.html b/tags/ci/page/1/index.html new file mode 100644 index 000000000..3c704eb5b --- /dev/null +++ b/tags/ci/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ci/ + \ No newline at end of file diff --git a/tags/cplusplus/index.html b/tags/cplusplus/index.html new file mode 100644 index 000000000..0ef277cf8 --- /dev/null +++ b/tags/cplusplus/index.html @@ -0,0 +1,55 @@ +Tag: Cplusplus - kurisaW +

Tags

1 page

Cplusplus

\ No newline at end of file diff --git a/tags/cplusplus/index.xml b/tags/cplusplus/index.xml new file mode 100644 index 000000000..9606cadae --- /dev/null +++ b/tags/cplusplus/index.xml @@ -0,0 +1,856 @@ +Cplusplus on kurisaWhttps://kurisaw.github.io/tags/cplusplus/Recent content in Cplusplus on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git a/tags/cplusplus/page/1/index.html b/tags/cplusplus/page/1/index.html new file mode 100644 index 000000000..562b70659 --- /dev/null +++ b/tags/cplusplus/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/cplusplus/ + \ No newline at end of file diff --git a/tags/csa/index.html b/tags/csa/index.html new file mode 100644 index 000000000..84555be44 --- /dev/null +++ b/tags/csa/index.html @@ -0,0 +1,55 @@ +Tag: CSA - kurisaW +

Tags

1 page

CSA

\ No newline at end of file diff --git a/tags/csa/index.xml b/tags/csa/index.xml new file mode 100644 index 000000000..aac2b26e4 --- /dev/null +++ b/tags/csa/index.xml @@ -0,0 +1,405 @@ +CSA on kurisaWhttps://kurisaw.github.io/tags/csa/Recent content in CSA on kurisaWHugo -- gohugo.ioenWed, 14 Jun 2023 00:00:00 +0000【Matter】Matter学习笔记1https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/<img src="https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover.jpg" alt="Featured image of post 【Matter】Matter学习笔记1" /><h1 id="matter学习笔记1">Matter学习笔记1 +</h1><hr> +<p>在了解Matter之前,可以选择先了解以下前提知识:</p> +<ul> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118389957" target="_blank" rel="noopener" +>matter网络基础之—Thread</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118553988" target="_blank" rel="noopener" +>matter网络基础之—Wi-Fi</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/119253287" target="_blank" rel="noopener" +>边界路由器,网关和Wi-Fi接入点</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/120067170" target="_blank" rel="noopener" +>Thread地址(IPv6 and RLOC16)</a></li> +</ul> +<blockquote> +<p>以上资料来自CSDN博主:<a class="link" href="https://blog.csdn.net/qq_42860989" target="_blank" rel="noopener" +>Eagle115</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。</p> +<p>Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个<strong>统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准</strong>。</p> +<p>Matter 作为一个<strong>应用级的协议</strong>,向下屏蔽了<strong>设备制造商的生态和系统,让各种智能家居设备之间能相互通信</strong>。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。</p> +<p>Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:</p> +<ul> +<li><strong>低功耗蓝牙技术</strong>:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。</li> +<li><strong>二维码进行配置</strong>:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。</li> +<li><strong>Wi-Fi 技术进行高速数据传输</strong>:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。</li> +<li><strong>Thread 协议进行低速数据传输</strong>:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。</li> +</ul> +<h2 id="matter协议架构">Matter协议架构 +</h2><h3 id="1matter-over-ipv6">1.Matter Over IPV6 +</h3><p>该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。</p> +<p>IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。</p> +<p>下面是IPV4 和 IPV6 的一些区别:</p> +<table> +<thead> +<tr> +<th style="text-align:center">区别</th> +<th style="text-align:center">IPV4</th> +<th style="text-align:center">IPV6</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">地址长度</td> +<td style="text-align:center">32 bits</td> +<td style="text-align:center">128 bits</td> +</tr> +<tr> +<td style="text-align:center">地址数量</td> +<td style="text-align:center">约<strong>4x10^9</strong></td> +<td style="text-align:center">约<strong>3.4×10^38</strong></td> +</tr> +<tr> +<td style="text-align:center">地址类型</td> +<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> +<td style="text-align:center">通过 DHCPv6 动态分配</td> +</tr> +<tr> +<td style="text-align:center">安全性</td> +<td style="text-align:center">IPsec(Internet协议安全标准) 为可选项</td> +<td style="text-align:center">IPsec 为默认选项</td> +</tr> +<tr> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +</tr> +</tbody> +</table> +<h3 id="2matter协议架构">2.Matter协议架构 +</h3><p>Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121952614.png" +loading="lazy" +></p> +<p>为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此<strong>天生具备IP连接能力</strong>,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;</p> +<p>Matter 还支持<strong>桥接</strong>等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行<strong>Bridge</strong>;</p> +<p>由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!</p> +<h3 id="3matter标准协议架构">3.Matter标准协议架构 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121138795.png" +loading="lazy" +></p> +<p><strong>Matter标准协议架构总体流程分析:</strong></p> +<p>首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议<a class="link" href="" >Message Reliability Protocol</a>);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。</p> +<p>后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!</p> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p>原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。</p> +<p>在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。</p> +<p>Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为<strong>Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层</strong>。而 <strong>6LoWPAN协议</strong> 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。</p> +<p>因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。</p> +<h3 id="mesh组网">Mesh组网 +</h3><p>在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。</p> +<p>目前最流行的全屋WiFi方案主要有两种:<strong>Mesh路由器组网</strong>和<strong>AC+AP</strong>两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。</p> +<p>无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,<strong>无线Mesh网络</strong>中的<strong>AP</strong>可以采用<strong>无线连接</strong>的方式进行互连,并且<strong>AP间可以建立多跳的无线链路</strong>。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +loading="lazy" +alt="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +></p> +<p>这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:</p> +<h3 id="1单一网络拓扑">1.单一网络拓扑 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121601076.png" +loading="lazy" +></p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121516744.png" +loading="lazy" +></p> +<p>在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是<strong>Thread/802.15.4网络</strong>、<strong>Wi-Fi网络</strong>或<strong>以太网网络</strong>。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,<strong>前提是所有段都在链路层桥接</strong>。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。</p> +<p>在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。</p> +<p>在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为<strong>Fabric</strong>。</p> +<blockquote> +<p>注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。</p> +</blockquote> +<h3 id="2星形网络拓扑">2.星形网络拓扑 +</h3><ul> +<li><strong>AP(Access Point)</strong>:WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。</li> +<li><strong>STA(Station)</strong>:STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。</li> +<li><strong>BR(Border Router)</strong>:指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。</li> +<li><strong>ED(End device)</strong>:指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +<li><strong>R(Router)</strong>:指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。</li> +<li><strong>SED(Sleepy End Device)</strong>:指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121605090.png" +loading="lazy" +></p> +<p>星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。<strong>外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。</strong></p> +<p>在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。</p> +<p>该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。</p> +<blockquote> +<p>注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。</p> +</blockquote> +<h2 id="设备数据模型date-model">设备数据模型(Date Model) +</h2><p>在 Matter 中的设备具有明确定义的<strong>数据模型</strong> (<strong>DM</strong>),这是对设备功能的分层建模。在此层次结构的顶层,有一个<strong>Device</strong>。</p> +<h3 id="1设备和端点nodeendpoint">1.设备和端点(Node、Endpoint) +</h3><p>所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。</p> +<p>一组节点包含了多组<strong>Endpoint(端点)</strong>。<strong>而每个端点都封装了一个功能集</strong>。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122042737.png" +loading="lazy" +></p> +<h3 id="2节点角色node-roles">2.节点角色(Node roles) +</h3><p>在Matter 中,每一个物理设备都被称之为<strong>Node</strong>,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!</p> +<p><strong>Node roles</strong>是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:</p> +<ul> +<li><strong>Commissioner :执行</strong><a class="link" href="https://developers.home.google.com/matter/primer/commissioning" target="_blank" rel="noopener" +>调试</a>的节点 。</li> +<li><strong>控制器</strong>:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>开/关灯开关</a>)具有控制器角色。</li> +<li><strong>Controlee</strong> : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>On/Off Light Switch</a>。开/关灯开关只能<em>是</em>控制器。它不能是受控人。</li> +<li><strong>OTA Provider</strong> : 可以提供 OTA 软件更新的节点。</li> +<li><strong>OTA 请求者</strong>:可以请求 OTA 软件更新的节点。</li> +</ul> +<h3 id="3集群cluster">3.集群(Cluster) +</h3><p>在一个<strong>Endpoint</strong>中,一个 Node 有一个或多个<strong>Clusters</strong>。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的<em>开/关</em>集群,或可调光端点上的<em>电平控制集群。</em></p> +<p>一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。</p> +<h4 id="31-属性attributes">3.1 属性(Attributes) +</h4><p>在最后一层,我们会找到<strong>Attributes</strong>,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122111729.png" +loading="lazy" +></p> +<h4 id="32-命令commands">3.2 命令(Commands) +</h4><p>除了 Attributes 之外,Clusters 还有<strong>Commands</strong>,也就是<strong>触发 Cluster 进行某种行为的指令</strong>。它们等同于Matter远程过程调用的 DM。命令类似于<em>动词</em>,例如<em>Door Lock</em>集群上的 <em>lock door</em>。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。</p> +<h4 id="33-事件events">3.3 事件(Events) +</h4><p>最后,Clusters 也可能有<strong>Events</strong>,它<strong>可以被认为是过去状态转换的记录</strong>。虽然属性代表<strong>当前状态</strong>,但事件是<strong>过去</strong>的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122122628.png" +loading="lazy" +></p> +<p><code>Endpoint 0</code>作为<code>Utility Clusters</code><strong>保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新</strong>。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。</p> +<h3 id="4-cluster分类">4. Cluster分类 +</h3><p>cluster可以定义为<strong>工具(Utility) Cluster</strong>或<strong>应用(Application) Cluster</strong>。</p> +<h4 id="41-工具utility-cluster">4.1 工具(Utility) Cluster +</h4><p>工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。</p> +<blockquote> +<p>作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。</p> +</blockquote> +<h4 id="42-应用application-cluster">4.2 应用(Application) Cluster +</h4><p>应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。</p> +<blockquote> +<p>应用cluster示例:</p> +<ul> +<li>On/Off cluster —— client向server发送命令</li> +<li>Temperature Measurement cluster —— server向client报告数据</li> +</ul> +</blockquote> +<p>应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。</p> +<blockquote> +<p>示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。</p> +</blockquote> +<h3 id="5-clients-and-servers">5. Clients and Servers +</h3><p>Clusters 可能是<strong>Client Cluster</strong>或<strong>Server Cluster</strong>。服务器是<strong>有状态的</strong>,保存属性、事件和命令;而客户端是 <strong>无状态的</strong>,其职责是启动与远程服务器集群的<strong>交互</strong>,从而执行:</p> +<ul> +<li><strong>读取</strong>和<strong>写入</strong>其远程属性。</li> +<li><strong>读取</strong>其远程事件。</li> +<li><strong>调用</strong>其远程命令。</li> +</ul> +<p>虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有<code>controller/peripheral</code> 或 <code>leader/follower</code>关系。相反,关系是水平的:任何 Cluster 都可以是<strong>Server</strong>或<strong>Client</strong>。因此,<strong>对于不同的集群和功能,节点可能既是服务器又是客户端。</strong></p> +<p>例如,我们可能有两个台灯:<strong>节点 A</strong>和<strong>节点 B</strong>。两个节点都实现了一个<em>开/关灯</em>设备类型。此设备类型包括控制其各自物理光输出的<em>开/关服务器集群。</em></p> +<p>但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现<em>开/关客户端</em>集群,以便它可以控制服务器集群。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122240843.png" +loading="lazy" +></p> +<p>在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。</p> +<p>在下一节中,我们将详细介绍客户端和服务器集群如何交互: <strong>Interaction Model(交互模型)</strong>。</p> +<h2 id="交互模型">交互模型 +</h2><h3 id="1概念">1.概念 +</h3><p>如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。<strong>交互模型</strong>(<strong>IM</strong>),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。</p> +<p><strong>节点通过以下方式相互交互:</strong></p> +<ul> +<li>读取和订阅属性和事件</li> +<li>写入属性</li> +<li>调用命令</li> +</ul> +<p>每当一个节点与另一个节点建立加密通信序列时,它们就构成了<strong>交互</strong>关系。<strong>Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成</strong>,可以理解为 Node 之间的 IM 级消息。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306140839728.png" +loading="lazy" +></p> +<p>Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。</p> +<h4 id="11-发起者initiators-和目标targets">1.1 发起者(Initiators )和目标(Targets) +</h4><p>在Matter中,节点的发起目标被称为<strong>发起者(Initiators )</strong>,而响应的节点则作为<strong>目标(Target)</strong>。一般来说,发起者是客户端集群,而目标是客户端集群。</p> +<h4 id="12-组groups">1.2 组(Groups) +</h4><p>在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。</p> +<p>为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。</p> +<h4 id="13-路径path">1.3 路径(Path) +</h4><p><strong>当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。</strong></p> +<blockquote> +<p>注:Path 也可以使用<strong>Groups</strong>或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。</p> +</blockquote> +<p>Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。</p> +<p>Matter Path 使用规范:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;path&gt; = &lt;node&gt; &lt;endpoint&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span><span class="line"><span class="cl">&lt;path&gt; = &lt;group ID&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。</p> +<h4 id="14-定时和非定时timed--untimed">1.4 定时和非定时(Timed &amp; Untimed) +</h4><p>有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。</p> +<h3 id="2-read-transactions">2. Read Transactions +</h3><p>与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。</p> +<h4 id="21-读取请求操作read-request-action">2.1 读取请求操作(Read Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>在此 Action 中,Initiator 会查询 Target 提供的以下请求:</p> +<ul> +<li><strong>属性请求</strong>:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。</li> +<li><strong>事件请求</strong>:目标请求事件的零个或多个路径列表。</li> +</ul> +<p>目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141108121.png" +loading="lazy" +></p> +<h4 id="22-报告请求数据report-data-action">2.2 报告请求数据(Report Data Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>在此 Action 中,Target 响应:</p> +<ul> +<li><strong>属性报告(Attribute Reports)</strong>:读取操作请求中请求的零个或多个报告属性的列表。</li> +<li><strong>事件报告(Event Reports)</strong>:零个或多个报告事件的列表。</li> +<li><strong>抑制响应(Suppress Response)</strong>:一个标志,用于确定是否应抑制对此操作的<strong>状态响应。</strong></li> +<li><strong>订阅 ID(Subscription ID)</strong>:如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。</li> +</ul> +<h4 id="23-状态响应动作status-response-action">2.3 状态响应动作(Status Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者 -&gt; 目标</strong></p> +</blockquote> +<p>一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。</p> +<p>一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。</p> +<p>状态响应操作仅包含一个<strong>状态字段</strong>,该字段将确认操作成功或显示失败代码。</p> +<h3 id="3-subscription-transaction">3. Subscription Transaction +</h3><h4 id="31-订阅请求操作subscribe-request-action">3.1 订阅请求操作(Subscribe Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。</p> +<p>订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。</p> +<p>订阅请求操作包含:</p> +<ul> +<li><strong>Min Interval Floor(最小间隔层)</strong>:报告之间的最小间隔。</li> +<li><strong>Max Interval Ceiling(最大区间上限)</strong>:报告之间的最大间隔。</li> +<li>Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。</li> +<li>Event Reports(事件报告):零个或多个报告事件的列表。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141332135.png" +loading="lazy" +></p> +<p>在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:<strong>Primed Published Data</strong>。</p> +<p>然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。</p> +<p>目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。</p> +<h4 id="32-订阅响应操作subscribe-response-action">3.2 订阅响应操作(Subscribe Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>这是订阅交易的最后一个操作,并结束了该过程。这包括:</p> +<ul> +<li><strong>Subscription ID(订阅 ID)</strong>:标识订阅的整数。</li> +<li><strong>Min Interval(最小间隔)</strong>:最终确定的报告之间的最小间隔。</li> +<li><strong>Max Interval(最大间隔)</strong>:<em>最终</em>确定<em>的</em>报告之间的最大间隔。</li> +</ul> +<h3 id="4-write-transactions">4. Write Transactions +</h3><h4 id="41-不定时写入事务untimed-write-transaction">4.1 不定时写入事务(Untimed Write Transaction) +</h4><h5 id="411-写请求操作write-request-action">4.1.1 写请求操作(Write Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>与读取请求操作类似,在此操作中,发起者为目标提供:</p> +<ul> +<li><strong>Write Requests(写入请求)</strong>:包含路径和数据的一个或多个元组的列表。</li> +<li><strong>Timed Request(定时请求)</strong>:一个标志,指示此操作是否是定时写入事务的一部分。</li> +<li><strong>Suppress Response(抑制响应)</strong>:指示是否应抑制响应状态操作的标志。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141423081.png" +loading="lazy" +></p> +<h5 id="412-写响应操作write-response-action">4.1.2 写响应操作(Write Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<h5 id="413-不定时写入限制untimed-write-restrictions">4.1.3 不定时写入限制(Untimed Write Restrictions) +</h5><p>写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。</p> +<h4 id="42-定时写入事务timed-write-transaction">4.2 定时写入事务(Timed Write Transaction) +</h4><p>在定时写入事务中比非定时写入事务多了几个步骤。</p> +<h5 id="421-定时请求操作timed-request-action">4.2.1 定时请求操作(Timed request action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。</p> +<h5 id="422-写请求操作write-request-action">4.2.2 写请求操作(Write Request Action) +</h5><p>与前面描述的 <strong>4.1.1 写请求操作</strong> 相同。</p> +<h5 id="423-写响应操作write-response-action">4.2.3 写响应操作(Write Response Action) +</h5><p>与前面描述的 <strong>4.1.2 写响应操作</strong> 相同。</p> +<h5 id="424-定时写入限制timed-write-restrictions">4.2.4 定时写入限制(Timed Write Restrictions) +</h5><p>定时请求动作、写请求动作和写响应动作是单播的。</p> +<h3 id="5调用事务">5.调用事务 +</h3><p><strong>调用事务</strong>用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。</p> +<p>与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 <strong>交互模型:1.4.定时和非定时</strong></p> +<h4 id="51-不定时调用事务">5.1 不定时调用事务 +</h4><h5 id="511-调用请求操作invoke-request-action">5.1.1 调用请求操作(Invoke Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:</p> +<ul> +<li><strong>Invoke Requests(调用请求):集群命令</strong>的路径(PATH)列表 ,以及命令的可选参数,名为 <strong>Command Fields</strong>。</li> +<li>Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。</li> +<li>Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。</li> +<li><strong>Interaction ID</strong>:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。</li> +</ul> +<h5 id="512-调用响应操作invoke-response-action">5.1.2 调用响应操作(Invoke Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:</p> +<ul> +<li><strong>Invoke Responses(调用响应)</strong>:发送的每个调用请求的命令响应或状态列表。</li> +<li>Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。</li> +</ul> +<h5 id="513-不定时调用限制">5.1.3 不定时调用限制 +</h5><p>Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。</p> +<h4 id="52-定时调用事务">5.2 定时调用事务 +</h4><p>与定时写入事务类似,定时调用事务也从定时请求操作开始。</p> +<h5 id="521-定时请求操作">5.2.1 定时请求操作 +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141539988.png" +loading="lazy" +></p> +<h5 id="522-调用请求操作invoke-request-action">5.2.2 调用请求操作(Invoke Request Action) +</h5><p>与前面描述的 <strong>5.1.1 调用请求操作</strong> 相同。</p> +<h5 id="523-调用响应操作invoke-response-action">5.2.3 调用响应操作(Invoke Response Action) +</h5><p>与前面描述的 <strong>5.1.2 调用响应操作</strong> 相同。</p> +<h5 id="524-定时调用限制timed-invoke-restrictions">5.2.4 定时调用限制(Timed Invoke Restrictions) +</h5><p>所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。</p> +<p>Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。</p> +<hr> +<h2 id="参考资料">参考资料 +</h2><ul> +<li><a class="link" href="https://developers.home.google.com/matter/primer/device-data-model#parts_list" target="_blank" rel="noopener" +>https://developers.home.google.com/matter/primer/device-data-model#parts_list</a></li> +<li><a class="link" href="https://www.bilibili.com/video/BV1NL411T7Kj/?spm_id_from=333.788&amp;vd_source=40334d7415493efea293dacb3c13f0b4" target="_blank" rel="noopener" +>Matter技术及关键特性介绍</a></li> +</ul> \ No newline at end of file diff --git a/tags/csa/page/1/index.html b/tags/csa/page/1/index.html new file mode 100644 index 000000000..68aebd4d7 --- /dev/null +++ b/tags/csa/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/csa/ + \ No newline at end of file diff --git "a/tags/c\350\257\255\350\250\200/index.html" "b/tags/c\350\257\255\350\250\200/index.html" new file mode 100644 index 000000000..7d5cf1f4d --- /dev/null +++ "b/tags/c\350\257\255\350\250\200/index.html" @@ -0,0 +1,55 @@ +Tag: C语言 - kurisaW +

Tags

2 pages

C语言

\ No newline at end of file diff --git "a/tags/c\350\257\255\350\250\200/index.xml" "b/tags/c\350\257\255\350\250\200/index.xml" new file mode 100644 index 000000000..f03892405 --- /dev/null +++ "b/tags/c\350\257\255\350\250\200/index.xml" @@ -0,0 +1,1843 @@ +C语言 on kurisaWhttps://kurisaw.github.io/tags/c%E8%AF%AD%E8%A8%80/Recent content in C语言 on kurisaWHugo -- gohugo.ioenSun, 29 Aug 2021 00:00:00 +0000C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p> \ No newline at end of file diff --git "a/tags/c\350\257\255\350\250\200/page/1/index.html" "b/tags/c\350\257\255\350\250\200/page/1/index.html" new file mode 100644 index 000000000..19b9056fd --- /dev/null +++ "b/tags/c\350\257\255\350\250\200/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/c%E8%AF%AD%E8%A8%80/ + \ No newline at end of file diff --git a/tags/d1s/index.html b/tags/d1s/index.html new file mode 100644 index 000000000..eed74a8e9 --- /dev/null +++ b/tags/d1s/index.html @@ -0,0 +1,55 @@ +Tag: D1s - kurisaW +

Tags

1 page

D1s

\ No newline at end of file diff --git a/tags/d1s/index.xml b/tags/d1s/index.xml new file mode 100644 index 000000000..b8c2be0f1 --- /dev/null +++ b/tags/d1s/index.xml @@ -0,0 +1,190 @@ +D1s on kurisaWhttps://kurisaw.github.io/tags/d1s/Recent content in D1s on kurisaWHugo -- gohugo.ioenThu, 19 Jan 2023 00:00:00 +0000RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p> \ No newline at end of file diff --git a/tags/d1s/page/1/index.html b/tags/d1s/page/1/index.html new file mode 100644 index 000000000..83dc4893e --- /dev/null +++ b/tags/d1s/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/d1s/ + \ No newline at end of file diff --git a/tags/easyflash/index.html b/tags/easyflash/index.html new file mode 100644 index 000000000..e669dd16a --- /dev/null +++ b/tags/easyflash/index.html @@ -0,0 +1,55 @@ +Tag: Easyflash - kurisaW +

Tags

1 page

Easyflash

\ No newline at end of file diff --git a/tags/easyflash/index.xml b/tags/easyflash/index.xml new file mode 100644 index 000000000..7f24e4a66 --- /dev/null +++ b/tags/easyflash/index.xml @@ -0,0 +1,1755 @@ +Easyflash on kurisaWhttps://kurisaw.github.io/tags/easyflash/Recent content in Easyflash on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul> \ No newline at end of file diff --git a/tags/easyflash/page/1/index.html b/tags/easyflash/page/1/index.html new file mode 100644 index 000000000..2f8a0865d --- /dev/null +++ b/tags/easyflash/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/easyflash/ + \ No newline at end of file diff --git a/tags/env/index.html b/tags/env/index.html new file mode 100644 index 000000000..e780c21f8 --- /dev/null +++ b/tags/env/index.html @@ -0,0 +1,55 @@ +Tag: Env - kurisaW +

Tags

1 page

Env

\ No newline at end of file diff --git a/tags/env/index.xml b/tags/env/index.xml new file mode 100644 index 000000000..1e240847e --- /dev/null +++ b/tags/env/index.xml @@ -0,0 +1,128 @@ +Env on kurisaWhttps://kurisaw.github.io/tags/env/Recent content in Env on kurisaWHugo -- gohugo.ioenThu, 12 May 2022 00:00:00 +0000env工具学习https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post env工具学习" /><h4 id="一基础配置">一、基础配置 +</h4><p>1.首先需要下载git并配置好相应的环境变量</p> +<p>2.双击env,在setting中设置</p> +<p><img src="https://img-blog.csdnimg.cn/709a490d50c24945a2b06409d51b3209.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这样就可以指定文件夹打开env工具了</p> +<h4 id="二基本命令学习">二、基本命令学习 +</h4><p>1.scons:编译</p> +<p><img src="https://img-blog.csdnimg.cn/976aba29a258481d9128f4b984f78139.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]" +></p> +<p><code>(1)scons:</code>编译并打印相关内部信息 +<code>(2)scons -c:</code>清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +<code>(3)scons -s:</code>编译而不打印具体的内部命令 +<code>(4)scons --target=XXX:</code>使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=iar +</span></span><span class="line"><span class="cl">scons --target=mdk4 +</span></span><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(5)scons -jN:</code>多线程编译目标,在多核计算机上可以使用此命令加快编译速度</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons -j4 //双核编译工程 +</span></span></code></pre></td></tr></table> +</div> +</div><p><!-- raw HTML omitted -->注意:一般不建议使用,容易将编译信息和错误混杂<!-- raw HTML omitted --> +<code>(6)scons --dist:</code>搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set RTT_CC=keil +</span></span><span class="line"><span class="cl">set RTT_EXEC_PATH=C:/Keilv5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.menuconfig +打开菜单配置界面,可用户自定义模块</p> +<p>4.scons进阶学习 +scons内置函数</p> +<ul> +<li> +<p>GetCurrentDir(): +获取当前路径。</p> +</li> +<li> +<p>Glob(&rsquo;*.c&rsquo;): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。</p> +</li> +<li> +<p>GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。</p> +</li> +<li> +<p>Split(str): +将字符串 str 分割成一个列表 list。</p> +</li> +<li> +<p>DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +<code>DefineGroup()</code> 函数的参数描述:</p> +</li> +</ul> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th style="text-align:center"><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td style="text-align:center">Group 的名字</td> +</tr> +<tr> +<td>src</td> +<td style="text-align:center">Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件</td> +</tr> +<tr> +<td>depend</td> +<td style="text-align:center">Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现</td> +</tr> +<tr> +<td>parameters</td> +<td style="text-align:center">配置其他参数,可取值见下表,实际使用时不需要配置所有参数</td> +</tr> +</tbody> +</table> +<p>parameters可加入的参数:</p> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>dirs</td> +<td>SConscript 文件路径</td> +</tr> +<tr> +<td>variant_dir</td> +<td>指定生成的目标文件的存放路径</td> +</tr> +<tr> +<td>duiplicate</td> +<td>设定是否拷贝或链接源文件到 variant_dir</td> +</tr> +</tbody> +</table> \ No newline at end of file diff --git a/tags/env/page/1/index.html b/tags/env/page/1/index.html new file mode 100644 index 000000000..005bbb787 --- /dev/null +++ b/tags/env/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/env/ + \ No newline at end of file diff --git a/tags/esp-c3/index.html b/tags/esp-c3/index.html new file mode 100644 index 000000000..ed6c25de4 --- /dev/null +++ b/tags/esp-c3/index.html @@ -0,0 +1,55 @@ +Tag: ESP-C3 - kurisaW +

Tags

4 pages

ESP-C3

\ No newline at end of file diff --git a/tags/esp-c3/index.xml b/tags/esp-c3/index.xml new file mode 100644 index 000000000..f8032320f --- /dev/null +++ b/tags/esp-c3/index.xml @@ -0,0 +1,1718 @@ +ESP-C3 on kurisaWhttps://kurisaw.github.io/tags/esp-c3/Recent content in ESP-C3 on kurisaWHugo -- gohugo.ioenMon, 19 Jun 2023 00:00:00 +0000【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)" /><h1 id="如何在linux平台下测试matter应用级通信虚拟设备">如何在Linux平台下测试Matter应用级通信(虚拟设备) +</h1><hr> +<h2 id="准备工作">准备工作 +</h2><h3 id="1-递归克隆matter仓库">1. 递归克隆Matter仓库 +</h3><p>执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果克隆过程中发生报错,请执行如下命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout v1.0 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2-matter依赖项安装">2. Matter依赖项安装 +</h3><p>Matter 构建依赖于以下软件包及环境库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果通过<code> build_examples.py</code> 和 <code>-with-ui</code> 变体进行构建,也要安装 SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-matter环境构建">3. Matter环境构建 +</h3><p>执行<code>scripts/activate.sh</code>脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190833624.png" +loading="lazy" +alt="image-20230619083303148" +></p> +<p>如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-安装zap">4. 安装zap +</h3><blockquote> +<p>注意:zap 包目前不可用<code>arm64</code>(比如在 Raspberry PI 上编译时)。</p> +</blockquote> +<ul> +<li>**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node -v +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果安装的话不出意外会出现版本号。</p> +<ul> +<li><strong>Step2:zap安装</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> connectedhomeip/scripts/tools/zap +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">python3 zap_download.py +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是安装日志:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip +</span></span><span class="line"><span class="cl">2023-06-19 13:29:20 root INFO Data downloaded, extracting ... +</span></span><span class="line"><span class="cl">2023-06-19 13:29:25 root INFO Done extracting. +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_INSTALL_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step3:配置zap环境变量</strong></li> +</ul> +<p>我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为<code>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly</code>,在此目录下有个 zap 脚本,我们这个位置一定要记住!!</p> +<p>设置<code>ZAP_DEVELOPMENT_PATH</code>环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step4:运行zap引导程序</strong></li> +</ul> +<p>执行如下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./run_zaptool.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>效果如下:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191346155.png" +loading="lazy" +alt="image-20230619134658521" +></p> +<ul> +<li><strong>Step4:为了方便我们后续使用zap,我们设置root终端下自启动:</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">vi ~/.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>.bashrc</code>文件最末添加如下代码,也就是配置zap环境变量</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出!</p> +<h2 id="应用程序构建">应用程序构建 +</h2><p>在官方文档中提供有两种构建方式:</p> +<ul> +<li>通过脚本构建</li> +<li>使用 Gn 和 Ninja 命令构建</li> +</ul> +<h3 id="1-通过脚本构建">1. 通过脚本构建 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build_script.sh EXAMPLE_DIR OUTPUT_DIR <span class="o">[</span>ARGUMENTS<span class="o">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>build_script.sh</code> 是脚本的文件名;</li> +<li><code>EXAMPLE_DIR</code> 是示例项目的目录路径;</li> +<li><code>OUTPUT_DIR</code> 是构建输出的目录路径;</li> +<li><code>[ARGUMENTS]</code> 是可选的其他参数,用于设置gn和ninja命令的选项。</li> +</ul> +<h4 id="11-构建示例">1.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ <span class="nv">chip_tests_zap_config</span><span class="o">=</span><span class="se">\&#34;</span>app1<span class="se">\&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190835972.png" +loading="lazy" +alt="image-20230619083551820" +></p> +<h4 id="12-运行构建">1.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./out/simulated/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190843752.png" +loading="lazy" +alt="image-20230619084309631" +></p> +<h3 id="2-通过-gn-和-ninja-构建应用程序">2. 通过 gn 和 ninja 构建应用程序 +</h3><h4 id="21-构建示例">2.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span><span class="line"><span class="cl">gn gen --check --root<span class="o">=</span>examples/placeholder/linux out/simulated --args<span class="o">=</span><span class="s2">&#34;chip_tests_zap_config=\&#34;app1\&#34;&#34;</span> +</span></span><span class="line"><span class="cl">ninja -C out/simulated +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22-运行构建">2.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./out/app1/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191510937.png" +loading="lazy" +alt="image-20230619151054483" +></p> +<h2 id="测试应用程序">测试应用程序 +</h2><p>在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191513515.png" +loading="lazy" +alt="image-20230619151353417" +></p> +<p>我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> out/debug +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./chip-tool onoff on 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff off 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> accepted-command-list 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> on-time 0x654321 <span class="m">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191530858.png" +loading="lazy" +alt="image-20230619153015727" +></p> +<p>具体更多的使用命令可参考:<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md" target="_blank" rel="noopener" +>Chip tool</a></p> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/simulated_device_linux.md" target="_blank" rel="noopener" +>simulated_device_linux</a></li> +<li><a class="link" href="https://github.com/project-chip/zap" target="_blank" rel="noopener" +>zap</a></li> +</ul>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/Sat, 06 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/<img src="https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover.jpg" alt="Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)" /><h1 id="esp-matter环境下的应用实践">esp-matter环境下的应用实践 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><p>请确保你本地已经配置好 <code>esp-idf</code> 及<code>esp-matter</code>环境,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130484975?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter开发环境搭建</a></p> +<h2 id="设置环境变量">设置环境变量 +</h2><h3 id="1esp-idf">1.ESP-IDF +</h3><p>根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041609281.png" +loading="lazy" +alt="image-20230504160909004" +></p> +<h3 id="2esp-matter">2.ESP-Matter +</h3><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>Linux</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>macOS</a></li> +</ul> +<p>由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>此处</a></p> +<p>在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>准备编译matter所需环境。注:如切换了其他分支需要重新运行</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060133538.png" +loading="lazy" +alt="image-20230506013329415" +></p> +<p>激活编译matter环境</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041611578.png" +loading="lazy" +alt="image-20230504161123505" +></p> +<h2 id="matter-example编译下载">Matter Example编译下载 +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2选择esp设备">2.选择esp设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>初次执行这个命令发生了如下报错:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">AttributeError</span><span class="p">:</span> <span class="err">&#39;</span><span class="n">HTTPResponse</span><span class="err">&#39;</span> <span class="n">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="err">&#39;</span><span class="n">strict</span><span class="err">&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在GitHub上参考此<a class="link" href="https://github.com/espressif/esp-idf/issues/11340" target="_blank" rel="noopener" +>issue</a>,并执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时重新执行esp-matter安装脚本:</p> +<p>由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此<a class="link" href="https://github.com/kurisaW/Summer-of-Open-Source/issues/7" target="_blank" rel="noopener" +>issue</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="p">.</span><span class="n">environment</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后回到示例工程下继续执行esp设备选择</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时发生了新的错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060221146.png" +loading="lazy" +alt="image-20230506022134054" +></p> +<p>由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">rm</span> <span class="o">-</span><span class="n">r</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span><span class="o">/</span><span class="n">build</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后成功解决问题:</p> +<p><img src="https://user-images.githubusercontent.com/98592772/236539480-35af78e1-382f-4092-a25b-fb2a09004d0a.png" +loading="lazy" +alt="b372338ad9384db034000d7839549b5" +></p> +<h3 id="3编译工程">3.编译工程 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060250998.png" +loading="lazy" +alt="image-20230506025001282" +></p> +<h3 id="4sdk烧写">4.SDK烧写 +</h3><p>第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">erase_flash</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060252819.png" +loading="lazy" +alt="image-20230506025047817" +></p> +<p>烧录程序并打开串口监视</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>可以看到烧录进度:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060251334.png" +loading="lazy" +alt="image-20230506025133178" +></p> +<p>包括串口监视器的提示信息,同时执行以下命令可退出串口监视:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">CTRL</span> <span class="o">+</span> <span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060254172.png" +loading="lazy" +alt="image-20230506025401001" +></p> +<p>那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。</p> +<hr> +<p>参考链接:</p> +<p><a class="link" href="https://blog.csdn.net/hydfxy2018/article/details/122041168?spm=1001.2101.3001.6650.11&amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;utm_relevant_index=12" target="_blank" rel="noopener" +>Matter Over Wifi 例程体验(CHIP Over Wifi)</a></p> +<p><a class="link" href="https://blog.csdn.net/weixin_40209493/article/details/125814311?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168324979316800211536064%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=168324979316800211536064&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-125814311-null-null.142%5ev86%5econtrol_2,239%5ev2%5einsert_chatgpt&amp;utm_term=matter%E6%8A%A5%E9%94%99&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>ESP-Matter 环境测试</a></p> +<p><a class="link" href="https://blog.csdn.net/puweiqi/article/details/129474079?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;utm_relevant_index=3" target="_blank" rel="noopener" +>matter搭建环境</a></p> +<p><a class="link" href="https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html" target="_blank" rel="noopener" +>https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html</a></p>【Matter】esp-matter开发环境搭建https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【Matter】esp-matter开发环境搭建" /><h1 id="esp-matter开发环境搭建">esp-matter开发环境搭建 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><h3 id="1ubuntu2204磁盘容量不小于80g">1.Ubuntu22.04(磁盘容量不小于80G) +</h3><h3 id="2科学上网环境">2.科学上网环境 +</h3><p>由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。</p> +<p>参考链接:<a class="link" href="https://kurisaw.github.io/p/%e7%bb%8f%e9%aa%8c%e5%88%86%e4%ba%ablinux-%e7%8e%af%e5%a2%83%e4%b8%8bv2ray%e7%9a%84%e4%bd%bf%e7%94%a8/" target="_blank" rel="noopener" +>【经验分享】Linux 环境下v2ray的使用</a></p> +<h2 id="esp-idf-开发环境搭建">esp-idf 开发环境搭建 +</h2><h3 id="1esp-idf-依赖环境安装">1.ESP-IDF 依赖环境安装 +</h3><blockquote> +<p>参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:</p> +<ul> +<li>Problem1:执行 git submodule 速度慢</li> +<li>Problem2:执行install.sh 速度慢</li> +</ul> +<p>所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。</p> +<h3 id="2problem1-solution">2.Problem1 solution +</h3><p>首先使用递归克隆命令克隆整个仓库到文件夹下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-idf.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span> <span class="o">--</span><span class="n">recursive</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:</p> +<ul> +<li>jihu-mirror 使用(推荐)</li> +<li>submodule-update 使用(不推荐)</li> +</ul> +<h4 id="21--jihu-mirror-使用推荐">2.1 jihu-mirror 使用(推荐) +</h4><ul> +<li>Step 1:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-gitee-tools.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Step 2:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 使用如下命令将仓库的 URL 进行替换: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">url</span><span class="p">.</span><span class="nl">https</span><span class="p">:</span><span class="c1">//jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>当我们使用命令 <code>git clone https://github.com/espressif/esp-idf</code> 时,默认的 URL <code>https://github.com/espressif/esp-idf</code> 将被自动替换成 <code>https://jihulab.com/esp-mirror/espressif/esp-idf</code>。</p> +<ul> +<li>Step 3:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 启用镜像URL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">set</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用命令 <code>./jihu-mirror.sh unset</code> 恢复,不使用镜像的 URL。</p> +<ul> +<li>Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recursive https://github.com/espressif/esp-idf.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然如果不想使用镜像的URL可以使用如下命令进行恢复:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">unset</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22--submodule-update-使用不推荐">2.2 submodule-update 使用(不推荐) +</h4><ul> +<li> +<p>Step 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">gitee</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">EspressifSystems</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">.</span><span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>Step 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 仅克隆 esp-idf,不包含子模块 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-idf.git +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<ul> +<li>Step 3:</li> +</ul> +<p>可以有两种方式来更新 submodules。</p> +<ul> +<li> +<p>方式一</p> +<p>进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">EGT_PATH</span><span class="o">=$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入 esp-idf 目录执行 submodule-update.sh 脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd esp-idf +</span></span><span class="line"><span class="cl">$EGT_PATH/submodule-update.sh +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>方式二</p> +<p><code>submodule-update.sh</code> 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:<code>submodule-update.sh PATH_OF_PROJ</code>。</p> +<p>假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="o">./</span><span class="n">submodule</span><span class="o">-</span><span class="n">update</span><span class="o">.</span><span class="n">sh</span> <span class="o">~/</span><span class="n">git</span><span class="o">/</span><span class="n">esp32</span><span class="o">-</span><span class="n">sdk</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果要更新其他工程,可以同样方式。</p> +</li> +</ul> +<blockquote> +<p>值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!</p> +</blockquote> +<h3 id="3problem2-solution">3.Problem2 solution +</h3><p>下面说第二个问题:执行./install.sh速度慢的问题</p> +<p>在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 <code>IDF_GITHUB_ASSETS</code> 的环境变量来指定这个地址。在设置了 <code>IDF_GITHUB_ASSETS</code> 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">export</span> <span class="n">IDF_GITHUB_ASSETS</span><span class="o">=</span><span class="s">&#34;dl.espressif.com/github_assets&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后再执行安装命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这还报了一个错误</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041247286.png" +loading="lazy" +alt="image-20230504124717772" +></p> +<p>我们根据提示安装<code>python3.10-venv</code>,并再次执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="mf">.10</span><span class="o">-</span><span class="n">venv</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041249721.png" +loading="lazy" +alt="image-20230504124913620" +></p> +<p>至此,esp-idf 的安装工具就告一段落了。</p> +<h2 id="esp-matter开发环境搭建-1">esp-matter开发环境搭建 +</h2><blockquote> +<p>参考:<a class="link" href="https://github.com/espressif/esp-matter" target="_blank" rel="noopener" +>【乐鑫 Matter SDK GitHub】</a></p> +</blockquote> +<p>**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:<code>./jihu-mirror.sh unset</code>取消esp镜像!! **</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-matter.git +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git submodule update --init --recursive +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错&hellip;</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): started +</span></span><span class="line"><span class="cl"> error: subprocess-exited-with-error +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> × python setup.py bdist_wheel did not run successfully. +</span></span><span class="line"><span class="cl"> │ exit code: 1 +</span></span><span class="line"><span class="cl"> ╰─&gt; See above for output. +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> note: This error originates from a subprocess, and is likely not a problem with pip. +</span></span><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): finished with status &#39;error&#39; +</span></span><span class="line"><span class="cl"> ERROR: Failed building wheel for pycryptodome +</span></span><span class="line"><span class="cl"> Running setup.py clean for pycryptodome +</span></span><span class="line"><span class="cl"> Building wheel for gevent (pyproject.toml): started +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ...... +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们查看<code>install.sh</code>文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">basedir</span><span class="o">=</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">ESP_MATTER_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="nb">pwd</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">MATTER_PATH</span><span class="o">=</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">export</span> ESP_MATTER_PATH +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Running Matter Setup&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/scripts/bootstrap.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Run the zap_download.py and extract the path of installed binary</span> +</span></span><span class="line"><span class="cl"><span class="c1"># eg output before cut: &#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># output after cut: zap/zap-v2023.03.06-nightly</span> +</span></span><span class="line"><span class="cl"><span class="c1"># TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged</span> +</span></span><span class="line"><span class="cl"><span class="nv">zap_path</span><span class="o">=</span><span class="sb">`</span>python3 <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --sdk-root <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --extract-root .zap 2&gt;/dev/null <span class="p">|</span> cut -d<span class="o">=</span> -f2<span class="sb">`</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Check whether the download is successful.</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="nv">$zap_path</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Failed to install zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"> deactivate +</span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span><span class="s2">/.zap&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> rm -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl">mkdir <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl">mv <span class="nv">$zap_path</span>/* <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/ +</span></span><span class="line"><span class="cl">rm -r <span class="nv">$zap_path</span> +</span></span><span class="line"><span class="cl">chmod +x <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/zap-cli +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Building host tools&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">gn --root<span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">&#34;</span> gen <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl">ninja -C <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Host tools built at: </span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">/out/host&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Exit Matter environment&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">deactivate +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for mfg_tool&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/tools/mfg_tool/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for Matter&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;All done! You can now run:&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34; . </span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">/export.sh&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install build-essential python3-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pkg-config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" +loading="lazy" +alt="image-20230504145216015" +></a></p> +<p>接着在安装<code>zap-cli</code>的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./install.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" +loading="lazy" +alt="image-20230504150238105" +></a></p> +<p>最后看到<code>All done!</code>即代表环境安装成功!</p> +<p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" +loading="lazy" +alt="image-20230504153243388" +></a></p> +<p>至此,esp-matter开发环境搭建成功!</p> \ No newline at end of file diff --git a/tags/esp-c3/page/1/index.html b/tags/esp-c3/page/1/index.html new file mode 100644 index 000000000..9118f976c --- /dev/null +++ b/tags/esp-c3/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/esp-c3/ + \ No newline at end of file diff --git a/tags/experience-sharing/index.html b/tags/experience-sharing/index.html new file mode 100644 index 000000000..ec1499953 --- /dev/null +++ b/tags/experience-sharing/index.html @@ -0,0 +1,56 @@ +Tag: Experience Sharing - kurisaW +

Tags

6 pages

Experience Sharing

\ No newline at end of file diff --git a/tags/experience-sharing/index.xml b/tags/experience-sharing/index.xml new file mode 100644 index 000000000..13c2c0213 --- /dev/null +++ b/tags/experience-sharing/index.xml @@ -0,0 +1,887 @@ +Experience Sharing on kurisaWhttps://kurisaw.github.io/tags/experience-sharing/Recent content in Experience Sharing on kurisaWHugo -- gohugo.ioenSat, 03 Feb 2024 15:00:00 +0000【经验分享】如何让你的终端实现自动补齐、历史回溯https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E5%A6%82%E4%BD%95%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%BB%88%E7%AB%AF%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E8%A1%A5%E9%BD%90%E5%8E%86%E5%8F%B2%E5%9B%9E%E6%BA%AF/cover.jpg" alt="Featured image of post 【经验分享】如何让你的终端实现自动补齐、历史回溯" /><h2 id="linux下配置">Linux下配置 +</h2><p>在 Linux 系统上配置 oh-my-zsh 并更改主题以及启用历史回溯非常简单。下面是详细步骤:</p> +<h3 id="步骤-1-安装-zsh">步骤 1: 安装 zsh +</h3><p>确保你的系统上已经安装了 zsh。你可以使用系统的包管理器进行安装。例如,在基于 Debian/Ubuntu 的系统上,你可以运行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install zsh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-2-安装-oh-my-zsh">步骤 2: 安装 oh-my-zsh +</h3><p>在终端中运行以下命令来安装 oh-my-zsh:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者,如果你没有安装 <code>curl</code>,可以使用 <code>wget</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-3-更改主题">步骤 3: 更改主题 +</h3><ol> +<li> +<p>打开 <code>~/.zshrc</code> 文件以编辑它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nano ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>找到 <code>ZSH_THEME</code> 行并更改主题。你可以在 <a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" target="_blank" rel="noopener" +>oh-my-zsh 主题库</a>中选择一个主题,例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">ZSH_THEME</span><span class="o">=</span><span class="s2">&#34;agnoster&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>保存并关闭文件。</p> +</li> +</ol> +<h3 id="步骤-4-启用历史回溯">步骤 4: 启用历史回溯 +</h3><p>oh-my-zsh 默认启用历史回溯。确保 <code>~/.zshrc</code> 中没有明确禁用该功能的设置。检查是否存在以下行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;yyyy-mm-dd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这将显示历史命令的时间戳。如果你想要简单地显示命令历史而不包含时间戳,可以将其设置为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">HIST_STAMPS</span><span class="o">=</span><span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤-5-重新启动-zsh-或打开新终端">步骤 5: 重新启动 zsh 或打开新终端 +</h3><p>在更改 <code>~/.zshrc</code> 文件后,你需要重新启动 zsh 或者打开一个新的终端窗口以应用更改。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,你的 oh-my-zsh 应该已经配置好,并且你可以享受新的主题和命令历史回溯功能。如果你在终端中输入 <code>zsh</code> 并按 Enter,也可以切换到 zsh 提示符,体验更改后的主题和配置。</p> +<h2 id="windwos下配置">Windwos下配置 +</h2><p>在 Windows 下,你可以使用一些工具来实现类似 oh-my-zsh 的命令历史显示和补全功能。其中之一是使用 PowerShell,并安装 <code>PSReadLine</code> 模块,它提供了丰富的命令行编辑和历史记录功能。</p> +<p>以下是在 PowerShell 中配置类似 oh-my-zsh 的历史记录显示的步骤:</p> +<ol> +<li> +<p><strong>安装 PSReadLine 模块:</strong> +打开 PowerShell 终端,并执行以下命令来安装 <code>PSReadLine</code> 模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Install-Module</span> <span class="n">-Name</span> <span class="n">PSReadLine</span> <span class="n">-Force</span> <span class="n">-SkipPublisherCheck</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>配置 PowerShell 用户配置文件:</strong> +执行以下命令打开 PowerShell 配置文件(如果不存在,会创建一个新文件):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">notepad</span> <span class="nv">$PROFILE</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p><strong>在配置文件中添加以下行:</strong> +在打开的配置文件中,添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Import-Module</span> <span class="n">PSReadLine</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-HistoryNoDuplicates:</span><span class="vm">$false</span> +</span></span><span class="line"><span class="cl"><span class="nb">Set-PSReadLineOption</span> <span class="n">-EditMode</span> <span class="n">Emacs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存并关闭文件。</p> +</li> +<li> +<p><strong>重新启动 PowerShell:</strong> +关闭当前的 PowerShell 终端,并重新打开一个新的终端。</p> +</li> +<li> +<p><strong>使用历史记录搜索:</strong> +可以在 PowerShell 终端中使用 <code>Ctrl + r</code> 来搜索并显示命令历史记录。输入字符,它会匹配历史记录中的命令。</p> +</li> +</ol>【经验分享】Linux环境下v2ray的使用https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABlinux%E7%8E%AF%E5%A2%83%E4%B8%8Bv2ray%E7%9A%84%E4%BD%BF%E7%94%A8/cover.jpg" alt="Featured image of post 【经验分享】Linux环境下v2ray的使用" /><h1 id="linux-环境下v2ray的使用">Linux 环境下v2ray的使用 +</h1><hr> +<blockquote> +<p>v2ray官方文档:<a class="link" href="https://v2raya.org/" target="_blank" rel="noopener" +>https://v2raya.org/</a></p> +</blockquote> +<h2 id="curl安装">curl安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">apt-get purge libcurl4 +</span></span><span class="line"><span class="cl">apt-get install curl +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray镜像脚本安装">v2ray镜像脚本安装 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">curl</span> <span class="o">-</span><span class="n">Ls</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.v2raya.org/go.sh | sudo bash +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041040498.png" +loading="lazy" +alt="image-20230504104013149" +></p> +<p>出现该提示信息则表示安装成功:<code>info: V2Ray v5.4.1 is installed.</code></p> +<p>接着关掉服务,因为 v2rayA 不依赖于该 systemd 服务,如果是 Xray内核,则需要把后面的v2ray替换xray</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">disable</span> <span class="n">v2ray</span> <span class="o">--</span><span class="n">now</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray软件安装">v2ray软件安装 +</h2><blockquote> +<p>仓库release地址:<a class="link" href="https://github.com/v2rayA/v2rayA/releases" target="_blank" rel="noopener" +>https://github.com/v2rayA/v2rayA/releases</a></p> +</blockquote> +<p>选择合适自己 Linux 内核架构,可以使用<code>dpkg --print-architecture</code>查看</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041050162.png" +loading="lazy" +alt="image-20230504105029122" +></p> +<p>这里我选择``下载到 Linux 共享文件夹</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041052416.png" +loading="lazy" +alt="image-20230504105226313" +></p> +<p>将共享文件夹下的<code>installer_debian_amd64_2.0.5.deb</code>文件保存到一个文件夹下,在任务管理器中选择使用软件安装打开并进行安装</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041054352.png" +loading="lazy" +alt="image-20230504105440300" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041053522.png" +loading="lazy" +alt="image-20230504105340371" +></p> +<h2 id="启动v2raya进程">启动v2raya进程 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">start</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="设置开机自启动">设置开机自启动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">systemctl</span> <span class="n">enable</span> <span class="n">v2raya</span><span class="p">.</span><span class="n">service</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="v2ray使用">v2ray使用 +</h2><p>打开火狐浏览器,输入 http://localhost:2017/</p> +<p>输入你要设置的用户名和密码,任意填写自己记着就好,最后点击创建</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041058629.png" +loading="lazy" +alt="image-20230504105825544" +></p> +<p>导入我们的机场订阅地址</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041100916.png" +loading="lazy" +alt="image-20230504105925321" +></p> +<p>选择想要使用的节点后,点击 Ready</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041106172.png" +loading="lazy" +alt="image-20230504110635073" +></p> +<h2 id="v2ray-settings">v2ray Settings +</h2><p>我们点击网页上右上角的Setting,进行如下修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041110129.png" +loading="lazy" +alt="image-20230504111011073" +></p> +<h2 id="测试">测试 +</h2><p>至此所有的配置就完成了,我们打开 youtube 测试一下,没有问题,可以进行开发了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041111183.png" +loading="lazy" +alt="image-20230504111116983" +></p>Wireshark网络抓包教程https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover.jpg" alt="Featured image of post Wireshark网络抓包教程" /><blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/HarveyH/article/details/113731485" target="_blank" rel="noopener" +>转自:WireShark 抓包使用教程&ndash;详细</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:</p> +<p>1、Wireshark软件下载和安装以及Wireshark主界面介绍。</p> +<p>2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。</p> +<p>3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。</p> +<h2 id="wireshark软件安装">Wireshark软件安装 +</h2><p>软件下载路径:<a class="link" href="https://www.wireshark.org/" target="_blank" rel="noopener" +>wireshark官网</a>。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。</p> +<p>如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:<a class="link" href="http://www.win10pcap.org/download/" target="_blank" rel="noopener" +>win10pcap兼容性安装包</a></p> +<h2 id="wireshark-开始抓包示例"><strong>Wireshark 开始抓包示例</strong> +</h2><p>先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。</p> +<p>1、打开wireshark 2.6.5,主界面如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102042369.png" +loading="lazy" +alt="image-20230410204240214" +></p> +<p>2、选择菜单栏上Capture -&gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043634.png" +loading="lazy" +alt="image-20230410204301558" +></p> +<p>3、wireshark启动后,wireshark处于抓包状态中。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043120.png" +loading="lazy" +alt="image-20230410204330881" +></p> +<p>4、执行需要抓包的操作,如ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>。</p> +<p>5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043973.png" +loading="lazy" +alt="image-20230410204349768" +></p> +<p>5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。</p> +<h2 id="wireshakr抓包界面">Wireshakr抓包界面 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044121.png" +loading="lazy" +alt="image-20230410204417023" +></p> +<p>说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --&gt; Coloring Rules。如下所示</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044221.png" +loading="lazy" +alt="image-20230410204435065" +></p> +<p><strong>WireShark 主要分为这几个界面</strong></p> +<p>1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --&gt; Display Filters。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045496.png" +loading="lazy" +alt="image-20230410204500320" +></p> +<p>2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045343.png" +loading="lazy" +alt="image-20230410204525166" +></p> +<p>3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为</p> +<p>(1)Frame: 物理层的数据帧概况</p> +<p>(2)Ethernet II: 数据链路层以太网帧头部信息</p> +<p>(3)Internet Protocol Version 4: 互联网层IP包头部信息</p> +<p>(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP</p> +<p>(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045382.png" +loading="lazy" +alt="image-20230410204540297" +></p> +<p><strong>TCP包的具体内容</strong></p> +<p>从下图可以看到wireshark捕获到的TCP包中的每个字段。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045329.png" +loading="lazy" +alt="image-20230410204557194" +></p> +<p>4. Dissector Pane(数据包字节区)。</p> +<h2 id="wireshark过滤器设置">Wireshark过滤器设置 +</h2><p>初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。</p> +<p>(1)抓包过滤器</p> +<p>捕获过滤器的菜单栏路径为Capture --&gt; Capture Filters。用于<strong>在抓取数据包前设置。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046204.png" +loading="lazy" +alt="image-20230410204620124" +></p> +<p>如何使用?可以在抓取数据包前设置如下。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046995.png" +loading="lazy" +alt="image-20230410204653927" +></p> +<p>ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047470.png" +loading="lazy" +alt="image-20230410204717268" +></p> +<p>(2)显示过滤器</p> +<p>显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047185.png" +loading="lazy" +alt="image-20230410204734985" +></p> +<p>执行ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取的数据包列表如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047584.png" +loading="lazy" +alt="image-20230410204753507" +></p> +<p>观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048361.png" +loading="lazy" +alt="image-20230410204815301" +></p> +<p>上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。</p> +<p><strong>wireshark过滤器表达式的规则</strong></p> +<p>1、抓包过滤器语法和实例</p> +<p>抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&amp;&amp; 与、|| 或、!非)</p> +<p>(1)协议过滤</p> +<p>比较简单,直接在抓包过滤框中直接输入协议名即可。</p> +<p>TCP,只显示TCP协议的数据包列表</p> +<p>HTTP,只查看HTTP协议的数据包列表</p> +<p>ICMP,只显示ICMP协议的数据包列表</p> +<p>(2)IP过滤</p> +<p>host 192.168.1.104</p> +<p>src host 192.168.1.104</p> +<p>dst host 192.168.1.104</p> +<p>(3)端口过滤</p> +<p>port 80</p> +<p>src port 80</p> +<p>dst port 80</p> +<p>(4)逻辑运算符&amp;&amp; 与、|| 或、!非</p> +<p>src host 192.168.1.104 &amp;&amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包</p> +<p>host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包</p> +<p>!broadcast 不抓取广播数据包</p> +<p>2、显示过滤器语法和实例</p> +<p>(1)比较操作符</p> +<p>比较操作符有== 等于、!= 不等于、&gt; 大于、&lt; 小于、&gt;= 大于等于、&lt;=小于等于。</p> +<p>(2)协议过滤</p> +<p>比较简单,直接在Filter框中直接输入协议名即可。<strong>注意:协议名称需要输入小写。</strong></p> +<p>tcp,只显示TCP协议的数据包列表</p> +<p>http,只查看HTTP协议的数据包列表</p> +<p>icmp,只显示ICMP协议的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048252.png" +loading="lazy" +alt="image-20230410204852057" +></p> +<p>(3) ip过滤</p> +<p>ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表</p> +<p>ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表</p> +<p>ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049772.png" +loading="lazy" +alt="image-20230410204937591" +></p> +<p>(4)端口过滤</p> +<p>tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。</p> +<p>tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。</p> +<p>tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049752.png" +loading="lazy" +alt="image-20230410204953546" +></p> +<p>(5) Http模式过滤</p> +<p>http.request.method==&ldquo;GET&rdquo;, 只显示HTTP GET方法的。</p> +<p>(6)逻辑运算符为 and/or/not</p> +<p>过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050123.png" +loading="lazy" +alt="image-20230410205019907" +></p> +<p>(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050553.png" +loading="lazy" +alt="image-20230410205039366" +></p> +<p>右键单击选中后出现如下界面</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050685.png" +loading="lazy" +alt="image-20230410205054595" +></p> +<p>选中Select后在过滤器中显示如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051573.png" +loading="lazy" +alt="image-20230410205109402" +></p> +<p>后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含&quot;abcd&quot;内容的数据流。<strong>包含的关键词是contains 后面跟上内容。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051902.png" +loading="lazy" +alt="image-20230410205121718" +></p> +<p>看到这, 基本上对wireshak有了初步了解。</p> +<h2 id="wireshark抓包分析tcp三次握手">Wireshark抓包分析TCP三次握手 +</h2><p>(1)TCP三次握手连接建立过程</p> +<p>Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;</p> +<p>Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;</p> +<p>Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051845.png" +loading="lazy" +alt="image-20230410205135665" +></p> +<p>(2)wireshark抓包获取访问指定服务端数据包</p> +<p>Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。</p> +<p>Step2:使用ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取IP。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051433.png" +loading="lazy" +alt="image-20230410205150253" +></p> +<p>Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052925.png" +loading="lazy" +alt="image-20230410205200760" +></p> +<p>图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。</p> +<p><strong>第一次握手数据包</strong></p> +<p>客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052226.png" +loading="lazy" +alt="image-20230410205215079" +></p> +<p>数据包的关键属性如下:</p> +<p>SYN :标志位,表示请求建立连接</p> +<p>Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据</p> +<p>Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据</p> +<p><strong>第二次握手的数据包</strong></p> +<p>服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052307.png" +loading="lazy" +alt="image-20230410205230236" +></p> +<p>数据包的关键属性如下:</p> +<p>[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK</p> +<p>Seq = 0 :初始建立值为0,表示当前还没有发送数据</p> +<p>Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)</p> +<p><strong>第三次握手的数据包</strong></p> +<p>客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052080.png" +loading="lazy" +alt="image-20230410205245006" +></p> +<p>数据包的关键属性如下:</p> +<p>ACK :标志位,表示已经收到记录</p> +<p>Seq = 1 :表示当前已经发送1个数据</p> +<p>Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。</p> +<p>就这样通过了TCP三次握手,建立了连接。开始进行数据交互</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053540.png" +loading="lazy" +alt="image-20230410205305433" +></p> +<p>下面针对数据交互过程的数据包进行一些说明:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053537.png" +loading="lazy" +alt="image-20230410205320467" +></p> +<p>数据包的关键属性说明</p> +<p>Seq: 1</p> +<p>Ack: 1: 说明现在共收到1字节数据</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053985.png" +loading="lazy" +alt="image-20230410205335911" +></p> +<p>Seq: 1<br> +Ack: 951: 说明现在服务端共收到951字节数据</p> +<p>在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053340.png" +loading="lazy" +alt="image-20230410205349152" +></p> +<p>其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。</p> +<h2 id="wireshark分析常用操作">Wireshark分析常用操作 +</h2><p>调整数据包列表中时间戳显示格式。调整方法为View --&gt;Time Display Format --&gt; Date and Time of Day。调整后格式如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102054848.png" +loading="lazy" +alt="image-20230410205401641" +></p>【经验分享】ARM常用汇编指令https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/Wed, 29 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABarm%E5%B8%B8%E7%94%A8%E6%B1%87%E7%BC%96%E6%8C%87%E4%BB%A4/cover.jpg" alt="Featured image of post 【经验分享】ARM常用汇编指令" /><h1 id="arm常用汇编指令">ARM常用汇编指令 +</h1><table> +<thead> +<tr> +<th>指令名称</th> +<th>作用</th> +</tr> +</thead> +<tbody> +<tr> +<td>EQU</td> +<td>给数字常量设置一个符号名,相当于C语言中的define</td> +</tr> +<tr> +<td>AREA</td> +<td>汇编一个新的代码段或者数据段</td> +</tr> +<tr> +<td>SPACE</td> +<td>分配内存空间</td> +</tr> +<tr> +<td>PRESERVE8</td> +<td>当前文件栈需要按照8字节对齐</td> +</tr> +<tr> +<td>EXPORT</td> +<td>声明一个符号具有全局属性,可被外部文件使用</td> +</tr> +<tr> +<td>DCD</td> +<td>以字为单位分配内存,要求4字节对齐,并要求初始化这些内存</td> +</tr> +<tr> +<td>PROC</td> +<td>定义子程序,与ENDP成对使用,表示子程序结束</td> +</tr> +<tr> +<td>WEAK</td> +<td>弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,即使外部文件没有定义也不出错。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>IMPORT</td> +<td>声明标号来自外部文件,与C语言的EXETERN关键字类似</td> +</tr> +<tr> +<td>B</td> +<td>跳转到一个标号</td> +</tr> +<tr> +<td>ALIGN</td> +<td>编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,默认为4字节对齐。要注意的是,这不是ARM的指令,而是编译器的,这里要放一起只是为了方便</td> +</tr> +<tr> +<td>END</td> +<td>到达文件的末尾,文件结束</td> +</tr> +<tr> +<td>IF,ELSE,ENDIF</td> +<td>汇编条件分支语句,与C语言的if else类似</td> +</tr> +<tr> +<td>MRS</td> +<td>加载特殊功能寄存器的值到特殊功能寄存器</td> +</tr> +<tr> +<td>CBZ</td> +<td>比较,如果结果为0则转移</td> +</tr> +<tr> +<td>CBNZ</td> +<td>比较,如果结果非0则转移</td> +</tr> +<tr> +<td>LDR</td> +<td>从存储器中加载字到一个寄存器中</td> +</tr> +<tr> +<td>LDR[伪指令]</td> +<td>加载一个立即数或者一个地址到一个寄存器中。</td> +</tr> +<tr> +<td>LDRH</td> +<td>从存储器中加载半字到一个寄存器中</td> +</tr> +<tr> +<td>LDRB</td> +<td>从存储器中加载字节到一个寄存器中</td> +</tr> +<tr> +<td>STR</td> +<td>把一个寄存器按字节存储到存储器中</td> +</tr> +<tr> +<td>STRH</td> +<td>把一个寄存器的低半字存储到存储器中</td> +</tr> +<tr> +<td>STRB</td> +<td>把一个寄存器的低字节存储到存储器中</td> +</tr> +<tr> +<td>LDMIA</td> +<td>加载多个字,并且在加载后自增基址寄存器</td> +</tr> +<tr> +<td>STMIA</td> +<td>存储多个字,并且在存储后自增基址寄存器</td> +</tr> +<tr> +<td>ORR</td> +<td>按位或</td> +</tr> +<tr> +<td>BX</td> +<td>直接跳转到由寄存器给定的地址</td> +</tr> +<tr> +<td>BL</td> +<td>跳转到标号对应的地址,并且把跳转前的下一条指令地址保存到LR</td> +</tr> +<tr> +<td>BLX</td> +<td>跳转到由寄存器REG给出的地址,并且根据REG的LSB切换处理器模式,还要把转移前的下一条指令地址保存到LR中。ARM(LSB=0),Thumb(LSB=1)。cortex-M3只在Thumb中运行,那就必须保证reg的LSB=1,否则会报错</td> +</tr> +</tbody> +</table>Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/Tue, 12 Apr 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABmicrosoft-visual-c-14.0-%E5%AE%89%E8%A3%85%E5%8F%8Apycocotools2.0%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E6%95%99%E5%AD%A6%E9%98%B2%E8%B8%A9%E5%9D%91/cover.jpg" alt="Featured image of post Microsoft Visual C++ 14.0 安装及Pycocotools2.0版本安装教学(防踩坑)" /><h2 id="1microsoft-visual-c-140安装">1、Microsoft Visual C++ 14.0安装 +</h2><p>这里附上百度网盘下载链接: +链接: <a class="link" href="https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1t5GWGymN6mFHDNlgrmD0yw?pwd=ec88</a> 提取码: ec88</p> +<p>下载完成后双击打开 +<img src="https://img-blog.csdnimg.cn/04150c3c158c4baab13f0646ab6bb578.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>默认下载方式即可</p> +<hr> +<h2 id="2pycocotools20版本安装">2、Pycocotools2.0版本安装 +</h2><h4 id="1准备材料">(1)准备材料: +</h4><ul> +<li><a class="link" href="https://github.com/cocodataset/cocoapi" target="_blank" rel="noopener" +>下载pycocotools安装包</a>(可直接git拉取到本地文件夹)</li> +</ul> +<h4 id="2源码配置">(2)源码配置 +</h4><p>打开下载好的pycocotools,双击打开<code>setup.py</code>(文件路径:\cocoapi\PythonAPI\setup.py)</p> +<p><img src="https://img-blog.csdnimg.cn/985a37a42b1043bc9dc87d3c3e4e1d0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这里<code>将蓝色部分删除,只保留红色部分</code>(切记需要执行这一步!!!)</p> +<p>开始界面找到所有应用并打开<code>Anaconda Powershell Prompt</code></p> +<p><img src="https://img-blog.csdnimg.cn/9ad6e210127c49c9bfb16f9fd9b65968.png" +loading="lazy" +></p> +<p>先打开自己创建的虚拟环境,这里我的虚拟环境为python_env,可供参考。</p> +<p>如上图所示进入到<code>\cocoapi\PythonAPI</code>该目录下</p> +<p>分别执行以下两个命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="o">--</span><span class="n">inplace</span> +</span></span><span class="line"><span class="cl"><span class="n">python</span> <span class="n">setup</span><span class="o">.</span><span class="n">py</span> <span class="n">build_ext</span> <span class="n">install</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/02ec23e44b3848609cc74c8c28368a0f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>执行pip list查看</p> +<p><img src="https://img-blog.csdnimg.cn/642adca979d64daba7f8d2164e88443c.png" +loading="lazy" +> +此时回到<code>\cocoapi\PythonAPI</code>目录下,可以看到生成了相关文件 +<img src="https://img-blog.csdnimg.cn/bdde5563cb794cf1962800f4656b71f5.png" +loading="lazy" +alt="在这里插入图片描述" +> +将<code>pycocotools</code>和<code>pycocotools.egg-info</code>文件夹复制到你所创建的虚拟环境中(位置:Anaconda3-&gt;envs-&gt;python_env-&gt;Lib-&gt;site-packages) +<img src="https://img-blog.csdnimg.cn/8dd05ee9c4724de4a2ba536ad84aec81.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>至此所有问题解决!</p>总结:开发板挂载根文件系统遇到的一些问题https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/Wed, 30 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E6%A1%A5%E6%8E%A5%E7%BD%91%E7%BB%9C%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E5%BC%80%E5%8F%91%E6%9D%BF%E6%8C%82%E8%BD%BD%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/cover.jpg" alt="Featured image of post 总结:开发板挂载根文件系统遇到的一些问题" /><h2 id="一桥接网络">一、桥接网络 +</h2><h4 id="1简介">1、简介 +</h4><p>是指需手动配置虚拟机的IP地址(IP地址可自定义,但要和主机在同一个网段下)子网掩码,网关,此时虚拟机相当于局域网的另一台电脑,占用一个IP地址</p> +<h4 id="注意避坑">注意避坑: +</h4><p>如果你的虚拟机选择了桥接模式,那么建议最好是不要使用校园网,因为一般校园网会需要验证登录,但是在虚拟机中好像并不会弹出登录界面(个人理解),因此你的网络在虚拟机中是无法运行的。</p> +<h4 id="2解决办法">2、解决办法: +</h4><p>&lt;1&gt;选择直接使用网线连接到电脑,然后在虚拟机中桥接选择自己对应的网卡即可,博主自己是没有连接网线的,所以我自己是没有采取这个办法的。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241318456.png" +loading="lazy" +alt="image-20230424131854375" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241319850.png" +loading="lazy" +alt="image-20230424131957782" +></p> +<p>&lt;2&gt;无线网卡连接</p> +<p>考虑到生活的便捷性,大多数人一般都是使用的无线网卡上网,所以这里我们采用连接自己的个人热点进行网络桥接(当然也可以选择WiFi热点,此处为个人热点指南,WiFi连接可同样参考)</p> +<p>如下配置:</p> +<ul> +<li>主机配置</li> +</ul> +<p>首先电脑win+R,输入<code>cmd</code>进入终端,然后输入命令:<code>ipconfig</code>,找到自己的热点网络信息</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320409.png" +loading="lazy" +alt="image-20230424132028276" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241320692.png" +loading="lazy" +alt="image-20230424132041431" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241321679.png" +loading="lazy" +alt="image-20230424132117501" +></p> +<ul> +<li>虚拟机配置</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322849.png" +loading="lazy" +alt="image-20230424132214739" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322385.png" +loading="lazy" +alt="image-20230424132233318" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl+alt+T打开终端,输入命令:vi /etc/network/interfaces +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241322519.png" +loading="lazy" +alt="image-20230424132250210" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">保存退出后,再次输入命令: +</span></span><span class="line"><span class="cl">首先将网卡关闭:ifdown eth0(一般桥接默认为eth0网卡) +</span></span><span class="line"><span class="cl">然后启用网卡:ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="二开发板端测试">二、开发板端测试: +</h2><p><code>以下内容为开发板挂载根文件系统,感兴趣的可以动手实践一下借鉴下面这篇博客</code></p> +<p><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124407302?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【Linux系统开发】x210开发板根目录文件系统构建</a></p> +<p>我们打开secureCRT:</p> +<p>开机先ping下虚拟机网络:<code>ping '虚拟机IP'</code></p> +<blockquote> +<p>注意:此处如果无法ping通虚拟机,一般是自己的虚拟机网络有问题,可以尝试输入以下命令解决</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="err">方法一:打开命令:</span><span class="n">sudo</span> <span class="n">gedit</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">NetworkManager</span><span class="o">/</span><span class="n">nm</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">settings</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">出现文件内容:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># This file is installed into /etc/NetworkManager, and is loaded by</span> +</span></span><span class="line"><span class="cl"><span class="c1"># NetworkManager by default. To override, specify: &#39;--config file&#39;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># during NM startup. This can be done by appending to DAEMON_OPTS in</span> +</span></span><span class="line"><span class="cl"><span class="c1"># the file:</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"><span class="c1"># /etc/default/NetworkManager</span> +</span></span><span class="line"><span class="cl"><span class="c1">#</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">main</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">plugins</span><span class="o">=</span><span class="n">ifupdown</span><span class="p">,</span><span class="n">keyfile</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">ifupdown</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="n">managed</span><span class="o">=</span><span class="bp">true</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">(这里</span><span class="n">false改成true</span><span class="err">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">方法二:虚拟机重置网卡 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ifdown eth0 +</span></span><span class="line"><span class="cl">ifup eth0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>当开发板ping通虚拟机后,我们在secureCRT控制台输入<code>reset</code>命令重启开发板</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323671.png" +loading="lazy" +alt="image-20230424132308595" +></p> +<p>这里的内核加载过程中再次出现了问题,显示我nfs服务端无回应</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323776.png" +loading="lazy" +alt="image-20230424132323723" +></p> +<p>解决:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mount -t nfs -o nolock &#39;开发板ipaddr ip&#39;:/root/rootfs/x210_rootfs //再次重新挂载根文件系统 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//NFC网络重启 +</span></span><span class="line"><span class="cl">/etc/init.d/nfs-kernel-server restart +</span></span><span class="line"><span class="cl">sudo /etc/init.d/networking start +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304241323050.png" +loading="lazy" +alt="image-20230424132335917" +></p> +<p>问题解决!</p> \ No newline at end of file diff --git a/tags/experience-sharing/page/1/index.html b/tags/experience-sharing/page/1/index.html new file mode 100644 index 000000000..e93ff34df --- /dev/null +++ b/tags/experience-sharing/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/experience-sharing/ + \ No newline at end of file diff --git a/tags/experience-sharing/page/2/index.html b/tags/experience-sharing/page/2/index.html new file mode 100644 index 000000000..7e9905a7f --- /dev/null +++ b/tags/experience-sharing/page/2/index.html @@ -0,0 +1,56 @@ +Tag: Experience Sharing - Pager 2 - kurisaW +

Tags

6 pages

Experience Sharing

\ No newline at end of file diff --git a/tags/fal/index.html b/tags/fal/index.html new file mode 100644 index 000000000..988aa34fa --- /dev/null +++ b/tags/fal/index.html @@ -0,0 +1,55 @@ +Tag: FAL - kurisaW +

Tags

1 page

FAL

\ No newline at end of file diff --git a/tags/fal/index.xml b/tags/fal/index.xml new file mode 100644 index 000000000..f0c2abc6a --- /dev/null +++ b/tags/fal/index.xml @@ -0,0 +1,1755 @@ +FAL on kurisaWhttps://kurisaw.github.io/tags/fal/Recent content in FAL on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul> \ No newline at end of file diff --git a/tags/fal/page/1/index.html b/tags/fal/page/1/index.html new file mode 100644 index 000000000..54cc6db06 --- /dev/null +++ b/tags/fal/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/fal/ + \ No newline at end of file diff --git a/tags/git/index.html b/tags/git/index.html new file mode 100644 index 000000000..24dc0ccdf --- /dev/null +++ b/tags/git/index.html @@ -0,0 +1,56 @@ +Tag: Git - kurisaW +

Tags

6 pages

Git

\ No newline at end of file diff --git a/tags/git/index.xml b/tags/git/index.xml new file mode 100644 index 000000000..32d5c0bb3 --- /dev/null +++ b/tags/git/index.xml @@ -0,0 +1,1651 @@ +Git on kurisaWhttps://kurisaw.github.io/tags/git/Recent content in Git on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Git版本控制】Github和Gitlab同时使用sshhttps://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover.jpg" alt="Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh" /><h2 id="前言">前言 +</h2><p>最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下</p> +<h2 id="本地生成公私密钥">本地生成公私密钥 +</h2><p>首先确保把之前的 ssh 信息清除,也可以将整个 <code>~/.ssh</code> 目录删除</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rm -rf ~/.ssh/* +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们分别生成 Github 和 Gitlab账号的 SSH 密钥</p> +<ul> +<li>Github 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意不要选择其他操作,一路回车即可</p> +<p>此时打开 <code>~/.ssh/</code> 目录可以看到生成了四个文件:<code>github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub</code></p> +<p>其中 <code>.pub</code> 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存</p> +<h2 id="远程仓库-ssh-填写公钥密钥">远程仓库 SSH 填写公钥密钥 +</h2><p>我们先打开 Github 的 Settings选项,然后选择 <code>SSH and GPG keys-&gt;New SSH key</code> ,<code>Title</code>可以随意拟定,<code>Key</code>需要查看刚刚的 <code>github_id-rsa.pub</code> 文件,并且复制到 Gitlab 的<code>key</code>一栏中;</p> +<p>Gitlab 的操作方式与 Github 类似,具体步骤:</p> +<p>打开 <code>Gitlab -&gt; 用户设置 -&gt; SSH密钥</code> ,在密钥一栏填入 <code>gitlab_id-rsa.pub</code>文件中的具体值,标题自拟即可。</p> +<h2 id="配置不同-host-的-ssh-key">配置不同 Host 的 SSH Key +</h2><p>回到 <code>~/.ssh/</code> 目录下,并且创建一个名为 <code>config</code> 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#github</span> +</span></span><span class="line"><span class="cl">Host github.com +</span></span><span class="line"><span class="cl"> Hostname ssh.github.com +</span></span><span class="line"><span class="cl"> Port <span class="m">443</span> +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/github_id-rsa +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#gitlab</span> +</span></span><span class="line"><span class="cl">host git.rt-thread.com +</span></span><span class="line"><span class="cl"> Hostname git.rt-thread.com +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/figure/ssh-config.png" +loading="lazy" +></p> +<h2 id="验证">验证 +</h2><p>使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置</p> +<ul> +<li>Github SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@github.com +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@rt-thread.com +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功</p> +<p><img src="https://kurisaw.github.io/figure/valid-ssh.png" +loading="lazy" +></p>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p>Github同步Gitee镜像仓库自动化脚本https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/Tue, 11 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%90%8C%E6%AD%A5gitee%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC/cover.jpg" alt="Featured image of post Github同步Gitee镜像仓库自动化脚本" /><h1 id="github同步gitee镜像仓库自动化脚本">Github同步Gitee镜像仓库自动化脚本 +</h1><hr> +<h2 id="前言">前言 +</h2><p>在软件开发中,使用Git作为代码管理工具是非常普遍的。而GitHub和Gitee则是我们熟知的两个在线Git代码托管平台。如果我们在这两个平台上都有代码仓库,并且希望实现自动同步,应该怎么做呢?这就需要使用GitHub Action中的Hub Mirror Action了。</p> +<h2 id="什么是hub-mirror-action">什么是Hub Mirror Action? +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111537579.png" +loading="lazy" +alt="image-20230411153729450" +></p> +<h3 id="1介绍">1.介绍 +</h3><p><a class="link" href="https://github.com/marketplace/actions/hub-mirror-action" target="_blank" rel="noopener" +>Hub Mirror Action</a>是GitHub Action中的一个组件,可以将GitHub仓库内容自动同步到Gitee上,也可以实现从Gitee到GitHub的自动同步。Hub Mirror Action提供了多种同步方式,支持单向同步和双向同步,可以在配置文件中进行灵活设置。</p> +<h3 id="2用法">2.用法 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Mirror the Github organization repos to Gitee.</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kunpengcompute</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }}</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># src_account_type: org</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># dst_account_type: org</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:详细使用案例请查看官方仓库 <a class="link" href="https://github.com/Yikun/hub-mirror-action" target="_blank" rel="noopener" +>https://github.com/Yikun/hub-mirror-action</a></p> +<h2 id="配置步骤">配置步骤 +</h2><h3 id="1生成密钥对">1.生成密钥对 +</h3><p>我们先在本地使用git命令行打开终端,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ssh</span><span class="o">-</span><span class="n">keygen</span> <span class="o">-</span><span class="n">t</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">f</span> <span class="o">~/</span><span class="n">Documents</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">key</span><span class="o">/</span><span class="n">id_rsa</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注:请确保文件夹<code>~/Documents/ssh-key/</code>存在,当然你也可以选择放置在其他地方</p> +<p>过程中一路回车即可,注意不要设置密码。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111543237.png" +loading="lazy" +alt="image-20230411154330166" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111551053.png" +loading="lazy" +alt="image-20230411155124878" +></p> +<h3 id="2github私钥配置">2.GitHub私钥配置 +</h3><p>首先为了存放自动化脚本,我们需要创建一个新的GitHub仓库,并为其配置相关环境。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111547966.png" +loading="lazy" +alt="image-20230411154716849" +></p> +<ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_PRIVATE_KEY</code>的secret,值为我们之前生成的密钥对中的私钥(id_rsa)</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111553202.png" +loading="lazy" +alt="image-20230411155314101" +></p> +<h3 id="3gitee公钥配置">3.Gitee公钥配置 +</h3><p>我们打开Gitee账号,进入<code>Settings-&gt;安全设置-&gt;SSH公钥</code></p> +<p>添加一个名为gitee_sync的公钥,值也就是我们前面生成的公钥(id_rsa.pub)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111558684.png" +loading="lazy" +alt="image-20230411155846562" +></p> +<h3 id="4gitee生成私人令牌">4.Gitee生成私人令牌 +</h3><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111559999.png" +loading="lazy" +alt="image-20230411155958898" +></p> +<p>令牌名称随意,同时复制生成的令牌值。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111601466.png" +loading="lazy" +alt="image-20230411160127393" +></p> +<h3 id="5github绑定gitee令牌">5.Github绑定Gitee令牌 +</h3><ul> +<li> +<p>依次点击<code>Settings-&gt;Secrets and variables-&gt;Actions</code></p> +</li> +<li> +<p>点击<code>New respository secret</code>,创建一个名为<code>GITEE_TOKEN</code>的secret,值为Gitee生成的令牌值</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111603849.png" +loading="lazy" +alt="image-20230411160340721" +></p> +<h3 id="6编写ci脚本">6.编写CI脚本 +</h3><p>将<code>ci_bot</code>仓库(放置及部署自动化脚本的仓库)下载到本地,同时创建这样的文件层次目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="n">ci_bot</span><span class="o">/</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="p">.</span><span class="n">github</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">workflows</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span><span class="err">——</span><span class="n">Sync</span><span class="p">.</span><span class="n">yml</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>Sync.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">push, delete, create ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出后,将本次修改push到远端仓库。</p> +<p>查看Action运行情况:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111611887.png" +loading="lazy" +alt="image-20230411161143741" +></p> +<h3 id="7多仓库同步推送">7.多仓库同步推送 +</h3><p>如果你想同时同步多个仓库,只需要完成如下修改</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">static_list 默认为&#39;&#39;, 配置后,仅同步静态列表,不会再动态获取需同步列表(黑白名单机制依旧生效),如“repo1,repo2,repo3”。</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111633375.png" +loading="lazy" +alt="image-20230411163307283" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111631352.png" +loading="lazy" +alt="image-20230411163135259" +></p> +<h3 id="8定时运行脚本">8.定时运行脚本 +</h3><p>为了方便该脚本每天定时完成自动同步任务,我们可以使用GitHub提供的schedule事件完成:</p> +<p>修改Sync.yml文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 0 * * *&#39;</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">delete</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">create</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="l">main ]</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Sync Github Repos To Gitee </span><span class="w"> </span><span class="c"># 名字随便起</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Yikun/hub-mirror-action@master </span><span class="w"> </span><span class="c"># 使用Yikun/hub-mirror-action</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">github/kurisaW </span><span class="w"> </span><span class="c"># 源端账户名(github)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst</span><span class="p">:</span><span class="w"> </span><span class="l">gitee/kurisaW </span><span class="w"> </span><span class="c"># 目的端账户名(gitee)</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_PRIVATE_KEY }} </span><span class="w"> </span><span class="c"># SSH密钥对中的私钥</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">dst_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITEE_TOKEN }} </span><span class="w"> </span><span class="c"># Gitee账户的私人令牌</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">account_type</span><span class="p">:</span><span class="w"> </span><span class="l">user </span><span class="w"> </span><span class="c"># 账户类型</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">clone_style</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https&#34;</span><span class="w"> </span><span class="c"># 使用https方式进行clone,也可以使用ssh</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">debug</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后会显示所有执行命令</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">force_update</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 启用后,强制同步,即强制覆盖目的端仓库</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">static_list</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;kurisaW_docs,rt-thread,my_tools,pkgs,Npdf,kurisaW.github.io&#34;</span><span class="w"> </span><span class="c"># 静态同步列表,在此填写需要同步的仓库名称,可填写多个</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;600s&#39;</span><span class="w"> </span><span class="c"># git超时设置,超时后会自动重试git操作</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>也就是说该自动化脚本会每天零时进行自动化脚本的运行,自动更新镜像仓库,同时如果该配置文件发生推送、删除和创建文件操作时也会触发Action行为。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111731377.png" +loading="lazy" +alt="image-20230411173142865" +></p> +<h2 id="总结">总结 +</h2><p>通过以上步骤,我们已经完成了GitHub同步Gitee镜像仓库自动化脚本配置的操作。Hub Mirror Action作为GitHub Action中的一个组件,可以帮助我们在两个平台之间实现代码自动同步,极大地减轻了我们手动同步代码的工作量。当然如果你有任何问题欢迎留言区提出,我将竭力为你解答。</p>【Git版本控制】Git命令详解https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/Fri, 17 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6git%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 【Git版本控制】Git命令详解" /><h2 id="前言">前言 +</h2><p>Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 <strong>回撤</strong>这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而<strong>版本管理工具能记录每次的修改</strong>,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。</p> +<p>下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。</p> +<h2 id="展示帮助信息">展示帮助信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git help -g +</span></span></code></pre></td></tr></table> +</div> +</div><p>The command output as below:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">The common Git guides are: +</span></span><span class="line"><span class="cl"> attributes Defining attributes per path +</span></span><span class="line"><span class="cl"> cli Git command-line interface and conventions +</span></span><span class="line"><span class="cl"> core-tutorial A Git core tutorial for developers +</span></span><span class="line"><span class="cl"> cvs-migration Git for CVS users +</span></span><span class="line"><span class="cl"> diffcore Tweaking diff output +</span></span><span class="line"><span class="cl"> everyday A useful minimum set of commands for Everyday Git +</span></span><span class="line"><span class="cl"> glossary A Git Glossary +</span></span><span class="line"><span class="cl"> hooks Hooks used by Git +</span></span><span class="line"><span class="cl"> ignore Specifies intentionally untracked files to ignore +</span></span><span class="line"><span class="cl"> modules Defining submodule properties +</span></span><span class="line"><span class="cl"> namespaces Git namespaces +</span></span><span class="line"><span class="cl"> repository-layout Git Repository Layout +</span></span><span class="line"><span class="cl"> revisions Specifying revisions and ranges for Git +</span></span><span class="line"><span class="cl"> tutorial A tutorial introduction to Git +</span></span><span class="line"><span class="cl"> tutorial-2 A tutorial introduction to Git: part two +</span></span><span class="line"><span class="cl"> workflows An overview of recommended workflows with Git +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">&#39;git help -a&#39; and &#39;git help -g&#39; list available subcommands and some concept guides. See &#39;git help &lt;command&gt;&#39; or &#39;git help &lt;concept&gt;&#39; to read about a specific subcommand or concept. +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到远程仓库的状态">回到远程仓库的状态 +</h2><p>抛弃本地所有的修改,回到远程仓库的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch --all &amp;&amp; git reset --hard origin/master +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重设第一个-commit">重设第一个 commit +</h2><p>也就是把所有的改动都重新放回工作区,并<strong>清空所有的 commit</strong>,这样就可以重新提交第一个 commit 了</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-ref -d HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看冲突文件列表">查看冲突文件列表 +</h2><p>展示工作区的冲突文件列表</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --name-only --diff-filter=U +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示工作区和暂存区的不同">展示工作区和暂存区的不同 +</h2><p>输出<strong>工作区</strong>和<strong>暂存区</strong>的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff +</span></span></code></pre></td></tr></table> +</div> +</div><p>还可以展示本地仓库中任意两个 commit 之间的文件变动:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff &lt;commit-id&gt; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区和最近版本的不同">展示暂存区和最近版本的不同 +</h2><p>输出<strong>暂存区</strong>和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --cached +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示暂存区工作区和最近版本的不同">展示暂存区、工作区和最近版本的不同 +</h2><p>输出<strong>工作区</strong>、<strong>暂存区</strong> 和本地最近的版本 (commit) 的 different (不同)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff HEAD +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="快速切换到上一个分支">快速切换到上一个分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout - +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除已经合并到-master-的分支">删除已经合并到 master 的分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch --merged master | grep -v &#39;^\*\| master&#39; | xargs -n 1 git branch -d +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示本地分支关联远程仓库的情况">展示本地分支关联远程仓库的情况 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -vv +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="关联远程分支">关联远程分支 +</h2><p>关联之后,git branch -vv 就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -u origin/mybranch +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者在 push 时加上 -u 参数</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin/mybranch -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程分支">列出所有远程分支 +</h2><p>-r 参数相当于:remote</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -r +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出本地和远程分支">列出本地和远程分支 +</h2><p>-a 参数相当于:all</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -a +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看远程分支和本地分支的对应关系">查看远程分支和本地分支的对应关系 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote show origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="远程删除了分支本地也想删除">远程删除了分支本地也想删除 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote prune origin +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="创建并切换到本地分支">创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程分支中创建并切换到本地分支">从远程分支中创建并切换到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b &lt;branch-name&gt; origin/&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地分支">删除本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -d &lt;local-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程分支">删除远程分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete &lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>或者</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin :&lt;remote-branchname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="重命名本地分支">重命名本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git branch -m &lt;new-branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签">查看标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag +</span></span></code></pre></td></tr></table> +</div> +</div><p>展示当前分支的最近的 tag</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git describe --tags --abbrev=0 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看标签详细信息">查看标签详细信息 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -ln +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="本地创建标签">本地创建标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag &lt;version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认 tag 是打在最近的一次 commit 上,如果需要指定 commit 打 tag:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ git tag -a &lt;version-number&gt; -m &#34;v1.0 发布(描述)&#34; &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="推送标签到远程仓库">推送标签到远程仓库 +</h2><p>首先要保证本地创建好了标签才可以推送标签到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin &lt;local-version-number&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>一次性推送所有标签,同步到远程仓库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --tags +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除本地标签">删除本地标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git tag -d &lt;tag-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除远程标签">删除远程标签 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push origin --delete tag &lt;tagname&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="切回到某个标签">切回到某个标签 +</h2><p>一般上线之前都会打 tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout -b branch_name tag_name +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="放弃工作区的修改">放弃工作区的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>放弃所有修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout . +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="恢复删除的文件">恢复删除的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rev-list -n 1 HEAD -- &lt;file_path&gt; #得到 deleting_commit +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git checkout &lt;deleting_commit&gt;^ -- &lt;file_path&gt; #回到删除文件 deleting_commit 之前的状态 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以新增一个-commit-的方式还原某一个-commit-的修改">以新增一个 commit 的方式还原某一个 commit 的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git revert &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-commit-的状态并删除后面的-commit">回到某个 commit 的状态,并删除后面的 commit +</h2><p>和 revert 的区别:reset 命令会抹去某个 commit id 之后的所有 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;commit-id&gt; #默认就是-mixed参数。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git reset --hard &lt;commit-id&gt; #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改上一个-commit-的描述">修改上一个 commit 的描述 +</h2><p>如果暂存区有改动,同时也会将暂存区的改动提交到上一个 commit</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看-commit-历史">查看 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看某段代码是谁写的">查看某段代码是谁写的 +</h2><p>blame 的意思为‘责怪’,你懂的。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git blame &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="显示本地更新过-head-的-git-命令记录">显示本地更新过 HEAD 的 git 命令记录 +</h2><p>每次更新了 HEAD 的 git 命令比如 commit、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支),就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后,而不仅仅是回到当前分支下的某个 commit 之后的状态。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reflog +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改作者名">修改作者名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git commit --amend --author=&#39;Author Name &lt;email@address.com&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="修改远程仓库的-url">修改远程仓库的 url +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote set-url origin &lt;URL&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="增加远程仓库">增加远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote add origin &lt;remote-url&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="列出所有远程仓库">列出所有远程仓库 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git remote +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="查看两个星期内的改动">查看两个星期内的改动 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git whatchanged --since=&#39;2 weeks ago&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把-a-分支的某一个-commit放到-b-分支上">把 A 分支的某一个 commit,放到 B 分支上 +</h2><p>这个过程需要 cherry-pick 命令,<a class="link" href="http://sg552.iteye.com/blog/1300713#bc2367928" target="_blank" rel="noopener" +>参考</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;branch-name&gt; &amp;&amp; git cherry-pick &lt;commit-id&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="给-git-命令起别名">给 git 命令起别名 +</h2><p>简化命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global alias.&lt;handle&gt; &lt;command&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">比如:git status 改成 git st,这样可以简化命令 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git config --global alias.st status +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="存储当前的修改但不用提交-commit">存储当前的修改,但不用提交 commit +</h2><p>详解可以参考<a class="link" href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137602359178794d966923e5c4134bc8bf98dfb03aea3000" target="_blank" rel="noopener" +>廖雪峰老师的 git 教程</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="保存当前状态包括-untracked-的文件">保存当前状态,包括 untracked 的文件 +</h2><p>untracked 文件:新建的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash -u +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-stashes">展示所有 stashes +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash list +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到某个-stash-的状态">回到某个 stash 的状态 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash apply &lt;stash@{n}&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="回到最后一个-stash-的状态并删除这个-stash">回到最后一个 stash 的状态,并删除这个 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash pop +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除所有的-stash">删除所有的 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git stash clear +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从-stash-中拿出某个文件的修改">从 stash 中拿出某个文件的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout &lt;stash@{n}&gt; -- &lt;file-path&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-tracked-的文件">展示所有 tracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files -t +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-untracked-的文件">展示所有 untracked 的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有忽略的文件">展示所有忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git ls-files --others -i --exclude-standard +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的文件">强制删除 untracked 的文件 +</h2><p>可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的 untracked 文件。clean 命令,<strong>注意两点</strong>:</p> +<ol> +<li>clean 后,删除的文件无法找回</li> +<li>不会影响 tracked 的文件的改动,只会删除 untracked 的文件</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;file-name&gt; -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制删除-untracked-的目录">强制删除 untracked 的目录 +</h2><p>可以用来删除新建的目录,<strong>注意</strong>:这个命令也可以用来删除 untracked 的文件。详情见上一条</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean &lt;directory-name&gt; -df +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示简化的-commit-历史">展示简化的 commit 历史 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --pretty=oneline --graph --decorate --all +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把某一个分支导出成一个文件">把某一个分支导出成一个文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git bundle create &lt;file&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从包中导入分支">从包中导入分支 +</h2><p>新建一个分支,分支内容就是上面 git bundle create 命令导出的内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone repo.bundle &lt;repo-dir&gt; -b &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="执行-rebase-之前自动-stash">执行 rebase 之前自动 stash +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rebase --autostash +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="从远程仓库根据-id拉下某一状态到本地分支">从远程仓库根据 ID,拉下某一状态,到本地分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git fetch origin pull/&lt;id&gt;/head:&lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="详细展示一行中的修改">详细展示一行中的修改 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git diff --word-diff +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="清除-gitignore-文件中记录的文件">清除 gitignore 文件中记录的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clean -X -f +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示所有-alias-和-configs">展示所有 alias 和 configs +</h2><p><strong>注意:</strong> config 分为:当前目录(local)和全局(golbal)的 config,默认为当前目录的 config</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --local --list (当前目录) +</span></span><span class="line"><span class="cl">git config --global --list (全局) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示忽略的文件">展示忽略的文件 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git status --ignored +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="commit-历史中显示-branch1-有的但是-branch2-没有-commit">commit 历史中显示 Branch1 有的,但是 Branch2 没有 commit +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log Branch1 ^Branch2 +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中显示-gpg-签名">在 commit log 中显示 GPG 签名 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --show-signature +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="删除全局设置">删除全局设置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config --global --unset &lt;entry-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="新建并切换到新分支上同时这个分支没有任何-commit">新建并切换到新分支上,同时这个分支没有任何 commit +</h2><p>相当于保存修改,但是重写 commit 历史</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git checkout --orphan &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="展示任意分支某一文件的内容">展示任意分支某一文件的内容 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git show &lt;branch-name&gt;:&lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-下来指定的单一分支">clone 下来指定的单一分支 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone -b &lt;branch-name&gt; --single-branch https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="clone-最新一次提交">clone 最新一次提交 +</h2><p>只会 clone 最近一次提交,将减少 clone 时间</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --depth=1 https://github.com/user/repo.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略某个文件的改动">忽略某个文件的改动 +</h2><p>关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><p>恢复 track 指定文件的改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git update-index --no-assume-unchanged path/to/file +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="忽略文件的权限变化">忽略文件的权限变化 +</h2><p>不再将文件的权限变化视作改动</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git config core.fileMode false +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="以最后提交的顺序列出所有-git-分支">以最后提交的顺序列出所有 Git 分支 +</h2><p>最新的放在最上面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git for-each-ref --sort=-committerdate --format=&#39;%(refname:short)&#39; refs/heads/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="在-commit-log-中查找相关内容">在 commit log 中查找相关内容 +</h2><p>通过 grep 查找,given-text:所需要查找的字段</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git log --all --grep=&#39;&lt;given-text&gt;&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="把暂存区的指定-file-放到工作区中">把暂存区的指定 file 放到工作区中 +</h2><p>不添加参数,默认是 -mixed</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reset &lt;file-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="强制推送">强制推送 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git push -f &lt;remote-name&gt; &lt;branch-name&gt; +</span></span></code></pre></td></tr></table> +</div> +</div>【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/Fri, 29 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%BD%BF%E7%94%A8tortoisegit%E4%B8%80%E9%94%AE%E6%89%98%E7%AE%A1%E5%B7%A5%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%8F%8A%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/cover.jpg" alt="Featured image of post 【Git版本控制】使用TortoiseGit一键托管工程代码及版本控制" /><h4 id="一了解tortoisegit">一、了解TortoiseGit +</h4><p>TortoiseGit 是 Git 的 Windows Shell 接口,基于 TortoiseSVN。它是开源的,可以完全使用免费提供的软件构建。</p> +<p>由于它不是针对特定 IDE(如 Visual Studio、Eclipse 或其他)的集成,因此您可以将它与您喜欢的任何开发工具以及任何类型的文件一起使用。与 TortoiseGit 的主要交互将使用 Windows 资源管理器的上下文菜单。</p> +<p>TortoiseGit 通过常规任务为您提供支持,例如提交、显示日志、区分两个版本、创建分支和标签、创建补丁等等。</p> +<p>它是在<a class="link" href="https://www.gnu.org/licenses/gpl-2.0" target="_blank" rel="noopener" +>GPL</a>下开发的。这意味着任何人都可以完全免费使用,包括在商业环境中,没有任何限制。源代码也是免费提供的,因此您甚至可以根据需要开发自己的版本。</p> +<h4 id="二安装giit及tortoisegit">二、安装GIit及TortoiseGit +</h4><ul> +<li>Git下载官网: <a class="link" href="https://gitforwindows.org/index.html" target="_blank" rel="noopener" +>https://gitforwindows.org/index.html</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4a21fd0a6bd1453ba31032ce73c67d73.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>TortoiseGit下载官网:<a class="link" href="https://tortoisegit.org/download/" target="_blank" rel="noopener" +>https://tortoisegit.org/download/</a></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ba9793defe4baa02684e53320b79bde4.png" +loading="lazy" +alt="image-20220720090147944" +></p> +<ul> +<li>同时下载语言包</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b9cb668ce4c7a1ba2cda1a6bab5a0a76.png" +loading="lazy" +></p> +<p>当然这里也有百度网盘链接,也可点击下方链接进行下载</p> +<p>链接:<a class="link" href="https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1eSmu-opC0nzMsL-5GrUHQg?pwd=dzbs</a> +提取码:dzbs</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/db691a46832cc291932ff63fcc3e9a74.png" +loading="lazy" +alt="image-20220720090721507" +></p> +<h4 id="三tortoisegit配置">三、TortoiseGit配置 +</h4><p>完成上述安装后,单击鼠标右键可发现Git及TortoiseGit相关选项</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67fb3421c49f0c5e90e76fa3c04c9b71.png" +loading="lazy" +alt="image-20220720091049882" +></p> +<p>这里选择TortoiseGit-Setting(上图已经完成汉化),选择语言修改为简体中文</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/853a58d535b9e2370949ccb7917b80b5.png" +loading="lazy" +alt="image-20220720091218159" +></p> +<p>配置用户,用户作为你操作git的个人标识,进入设置,点选左边的Git标签,可以发现,右边可以配置用户的名字与Email信息. 如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/e70b76490f6f5cfc699d79df3968e1fe.png" +loading="lazy" +alt="image-20220720091439829" +></p> +<p>点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容(记住密码):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[credential] +</span></span><span class="line"><span class="cl"> helper = store +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成后保存,关闭记事本,确定即可。</p> +<p>  则当你使用 HTTPS URL 方式推送项目到GitHub等在线仓库时,海龟git会记住你输入的用户名和密码(这里不是用户的姓名和Email),可以避免每次提交都要输入用户名和密码。</p> +<p>  如果你编辑的是 本地 .git/config(L),其实这个翻译为本地有点问题,应该叫局部,也就是在某个项目下面设置,只对此项目有效,配置是一样的。</p> +<h4 id="四添加github-ssh-keys及密钥上传">四、添加GitHub SSH Keys及密钥上传 +</h4><p>首先找到想要选择的仓库克隆到本地的一个文件夹,然后找到你们安装TortoiseGit的位置(\TortoiseGit\bin\puttygen.exe),点击Generate生成钥匙,等待进度条结束后,保存公钥和私钥位置(记住位置)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/33d7c521e31040d4921e11ab1b12bd74.png" +loading="lazy" +alt="image-20220720092721281" +> +<img src="https://img-blog.csdnimg.cn/img_convert/3f27c4682dc82b0bd0f3ef5c89a1df7e.png" +loading="lazy" +alt="image-20220720093308539" +></p> +<p>然后复制下方公钥,</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2a5f6daf15cc2e9935764b207b726cf7.png" +loading="lazy" +alt="image-20220720093236525" +></p> +<p>打开github,完成下图操作:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/52cf49261a89b3186083dfb7240ea8dd.png" +loading="lazy" +alt="image-20220815182247315" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/1db55857a0118c8cabc02f9a5c4bb19b.png" +loading="lazy" +alt="image-20220815182404425" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b406ac32656957356de898117c6bb17f.png" +loading="lazy" +alt="image-20220815182541297" +></p> +<h4 id="五使用tortoisegit提交代码到远端仓库">五、使用TortoiseGit提交代码到远端仓库 +</h4><p>在Github自建一个仓库(自行选择即可,用于代码托管和版本控制),使用Git clone命令复制到本地文件夹</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/846315f99c2e767666f7be83437e4969.png" +loading="lazy" +alt="image-20220815185026555" +></p> +<p>鼠标右键可以看到选项<code>Git在这里创建版本库</code>,点击创建版本库</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bcb80e2391a690906240fd0d1b197e7a.png" +loading="lazy" +alt="image-20220815185825412" +></p> +<p>鼠标右键打开TortoiseGit-&gt;设置(Settings)-&gt;Git-&gt;远端(Remote),进行如下配置</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a1f9b059fb25b079395ad2588d51c0c5.png" +loading="lazy" +alt="image-20220815191405483" +></p> +<p>此时就可以将需要托管的代码放到这个文件夹内,然后进行代码的托管和版本控制了,下面简单做个示范:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9c4fbf6ee5360e497644e6330255a278.png" +loading="lazy" +alt="image-20220815190637369" +></p> +<p>我们创建一个文本文件,可以发现在文件上还有一个附带的图标显示,这分别代表不同的文件状态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">正常的:绿色的对号 +</span></span><span class="line"><span class="cl">被修改过的:红色感叹号 +</span></span><span class="line"><span class="cl">新添加的:蓝色的加号 +</span></span><span class="line"><span class="cl">未受控的(无版本控制的):蓝色的问号 +</span></span><span class="line"><span class="cl">忽略不受控的:灰色的减号 +</span></span><span class="line"><span class="cl">删除的:红色的x号 +</span></span><span class="line"><span class="cl">有冲突的:黄色的感叹号 +</span></span></code></pre></td></tr></table> +</div> +</div><p>鼠标右键添加文件</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f146752e79d7bd6a4e9287e2c32ad3c1.png" +loading="lazy" +alt="image-20220815191829438" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/50b75011172011ae724d81bd921f8fdc.png" +loading="lazy" +alt="image-20220815191933736" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/a9acdcdf6d14730de5e91df7564f65f8.png" +loading="lazy" +alt="image-20220815192002035" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/6439911282c3c25bde45fa033f3a58b3.png" +loading="lazy" +alt="image-20220815192321480" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/73d32ab54fc9914ea2d1a967c5b91065.png" +loading="lazy" +alt="image-20220815193032859" +></p> +<p><strong><code>注意:由于代理问题,需要开加速器,然后会出现拉取或提交失败,这都是正常现象,多试几次</code></strong></p> +<p>总结:使用TortoiseGit提交代码到远端仓库的步骤(配置完成后)</p> +<p><em><strong><code>添加-&gt;提交-&gt;拉取-&gt;推送</code></strong></em></p> +<p>那么以上就是TortoiseGit配置及代码托管的所有教学了,有问题欢迎在评论区或私信提问!</p> \ No newline at end of file diff --git a/tags/git/page/1/index.html b/tags/git/page/1/index.html new file mode 100644 index 000000000..21163f95a --- /dev/null +++ b/tags/git/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/git/ + \ No newline at end of file diff --git a/tags/git/page/2/index.html b/tags/git/page/2/index.html new file mode 100644 index 000000000..0be10d599 --- /dev/null +++ b/tags/git/page/2/index.html @@ -0,0 +1,56 @@ +Tag: Git - Pager 2 - kurisaW +

Tags

6 pages

Git

\ No newline at end of file diff --git a/tags/harmonyos/index.html b/tags/harmonyos/index.html new file mode 100644 index 000000000..ff5f9b016 --- /dev/null +++ b/tags/harmonyos/index.html @@ -0,0 +1,55 @@ +Tag: HarmonyOS - kurisaW +

Tags

1 page

HarmonyOS

\ No newline at end of file diff --git a/tags/harmonyos/index.xml b/tags/harmonyos/index.xml new file mode 100644 index 000000000..a157723e8 --- /dev/null +++ b/tags/harmonyos/index.xml @@ -0,0 +1,306 @@ +HarmonyOS on kurisaWhttps://kurisaw.github.io/tags/harmonyos/Recent content in HarmonyOS on kurisaWHugo -- gohugo.ioenFri, 07 Apr 2023 00:00:00 +0000【HarmonyOS】小熊派鸿蒙系统搭建https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/harmonyos%E5%B0%8F%E7%86%8A%E6%B4%BE%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【HarmonyOS】小熊派鸿蒙系统搭建" /><h2 id="一bearpi-hm-micro-开发板介绍">一、BearPi-HM Micro 开发板介绍 +</h2><p>BearPi-HM Micro开发板是一块高度集成并可运行Openharmony系统的开发板,板载高性能的工业级处理器STM32MP157芯片,搭配4.3寸LCD电容式触摸屏,并板载wifi电路及标准的E53接口,标准的E53接口可扩展智能加湿器、智能台灯、智能安防、智能烟感等案例。可折叠式屏幕设计大大提高用户开发体验,便于携带和存放,更好地满足不同用户的需求,拓展无限可能。</p> +<h2 id="二linux镜像下载">二、Linux镜像下载 +</h2><p>下载官方提供镜像(任选一种方式下载)</p> +<ul> +<li>Ubuntu20.04(大小8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1W0cgtXC5T2bv0lAya7eizA" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1W0cgtXC5T2bv0lAya7eizA</a> 提取码:1234</li> +<li>Ubuntu18.04(大小4.8G)下载地址(百度云):<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fpan.baidu.com%2Fs%2F1YIdqlRWRGq_heAfrgQ7EPQ" target="_blank" rel="noopener" +>https://pan.baidu.com/s/1YIdqlRWRGq_heAfrgQ7EPQ</a> 提取码:1234</li> +</ul> +<h2 id="三bearpi-hm-micro编译环境配置">三、BearPi-HM Micro编译环境配置 +</h2><p>在完成上面的镜像下载后,我们需要对BearPi-HM Micro环境进行编译环境的配置</p> +<h4 id="1首先添加如下镜像源">1.首先添加如下镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /etc/apt/source.list +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 添加中科大源 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">deb</span><span class="o">-</span><span class="n">src</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2更新镜像源">2.更新镜像源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get update +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3安装依赖库及工具">3.安装依赖库及工具 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">gcc</span> <span class="n">g</span><span class="o">++</span> <span class="n">make</span> <span class="n">zlib</span><span class="o">*</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">e2fsprogs</span> <span class="n">pkg</span><span class="o">-</span><span class="n">config</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">perl</span> <span class="n">bc</span> <span class="n">openssl</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">libelf</span><span class="o">-</span><span class="n">dev</span> <span class="n">libc6</span><span class="o">-</span><span class="n">dev</span><span class="o">-</span><span class="n">amd64</span> <span class="n">binutils</span> <span class="n">binutils</span><span class="o">-</span><span class="n">dev</span> <span class="n">libdwarf</span><span class="o">-</span><span class="n">dev</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">tools</span> <span class="n">mtd</span><span class="o">-</span><span class="n">utils</span> <span class="n">gcc</span><span class="o">-</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabi</span> <span class="n">cpio</span> <span class="n">device</span><span class="o">-</span><span class="n">tree</span><span class="o">-</span><span class="n">compiler</span> <span class="n">net</span><span class="o">-</span><span class="n">tools</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> <span class="n">git</span> <span class="n">vim</span> <span class="n">openjdk</span><span class="o">-</span><span class="mi">11</span><span class="o">-</span><span class="n">jre</span><span class="o">-</span><span class="n">headless</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装hb">4.安装hb +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 安装hb命令 +</span></span><span class="line"><span class="cl">python3 -m pip install --user ohos-build==0.4.3 +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 环境变量配置</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 在.bashrc文件最后一行添加如下代码,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/.</span><span class="n">local</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5测试hb是否安装成功">5.测试hb是否安装成功 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb -h +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071818214.png" +loading="lazy" +alt="image-20230407181805793" +></p> +<h2 id="四安装mkimage工具">四、安装mkimage工具 +</h2><p>首先解释这个工具的用途:<strong>用来制作不压缩或者压缩的多种可启动映象文件。</strong></p> +<h4 id="1新建tools目录">1.新建tools目录 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">~/</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2下载mkimagestm32工具到tools目录并复制到homebearpitools目录下">2.下载mkimage.stm32工具到<code>~/tools</code>目录,并复制到/home/bearpi/tools/目录下 +</h4><ul> +<li><a class="link" href="https://pan.baidu.com/share/init?surl=T2O8luJ0-8g5ZZYdOvWfqQ" target="_blank" rel="noopener" +>mkimage.stm32下载地址</a> 提取码:1234</li> +</ul> +<h4 id="3修改mkimagestm32文件权限">3.修改mkimage.stm32文件权限 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chmod</span> <span class="mi">777</span> <span class="o">~/</span><span class="n">tools</span><span class="o">/</span><span class="n">mkimage</span><span class="o">.</span><span class="n">stm32</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4设置环境变量">4.设置环境变量 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">vim</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 将下面的代码拷贝至.bashrc文件最后,并保存退出</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">PATH</span><span class="o">=~/</span><span class="n">tools</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新环境变量</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="o">~/.</span><span class="n">bashrc</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="五bearpi镜像导入vmware">五、bearpi镜像导入VMware +</h2><p>准备好前面的Linux镜像,并解压该文件,打开VMware station,选择上方导航栏:文件-&gt;打开(O),选择我们Linux镜像中的<code>BearPi-HM_Micro_Ubuntu.ovf</code>文件,等待镜像文件的导入,开始登录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">账户:bearpi +</span></span><span class="line"><span class="cl">密码:bearpi +</span></span></code></pre></td></tr></table> +</div> +</div><p>首先将网络连接模式更改为NAT模式,选择上方导航栏:虚拟机(M)-&gt;设置-&gt;网络适配器-&gt;NAT模式</p> +<p>此时打开一个终端,输入ifconfig查看ip</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071852103.png" +loading="lazy" +alt="image-20230407185206621" +></p> +<h2 id="六源码获取">六、源码获取 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mkdir project &amp;&amp; cd project +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">git clone https://gitee.com/bearpi/bearpi-hm_micro_small.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七编译代码">七、编译代码 +</h2><p>首先进入到项目文件夹中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd /home/bearpi/project/bearpi-hm_micro_small/ +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行如下命令(普通用户模式终端下):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb set +</span></span></code></pre></td></tr></table> +</div> +</div><p>出现<code>[OHOS INFO] Input code path: </code>提示信息后再输入<code>.</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071902001.png" +loading="lazy" +alt="image-20230407190200859" +></p> +<p>我们选择<code>bearpi-hm_micro</code>后回车</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071904137.png" +loading="lazy" +alt="image-20230407190426957" +></p> +<p>输入下面的命令,等待下载程序完成</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">hb build -t notest --tee -f +</span></span></code></pre></td></tr></table> +</div> +</div><p>当出现<code>build success</code>时,即代表编译成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071916323.png" +loading="lazy" +alt="image-20230407191628183" +></p> +<h2 id="八查看编译出的固件位置">八、查看编译出的固件位置 +</h2><p>当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在: <code>/home/bearpi/project/bearpi-hm_micro_small/out/bearpi_hm_micro/bearpi_hm_micro</code> 其中有以下文件是后面烧录系统需要使用的。</p> +<ul> +<li>OHOS_Image.stm32:系统镜像文件</li> +<li>rootfs_vfat.img:根文件系统</li> +<li>userfs_vfat.img:用户文件系统</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071919790.png" +loading="lazy" +alt="image-20230407191938678" +></p> +<p>我们将这三个文件复制到该目录下:<code>/home/bearpi/project/bearpi-hm_micro_small/applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/</code>,方便后续烧录系统使用</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="n">OHOS_Image</span><span class="o">.</span><span class="n">stm32</span> <span class="n">rootfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="n">userfs_vfat</span><span class="o">.</span><span class="n">img</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">bearpi</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">bearpi</span><span class="o">-</span><span class="n">hm_micro_small</span><span class="o">/</span><span class="n">applications</span><span class="o">/</span><span class="n">BearPi</span><span class="o">/</span><span class="n">BearPi</span><span class="o">-</span><span class="n">HM_Micro</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">download_img</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071929824.png" +loading="lazy" +alt="image-20230407192926584" +></p> +<h2 id="九固件烧录">九、固件烧录 +</h2><h4 id="1准备工作">1.准备工作 +</h4><ul> +<li><a class="link" href="https://www.wch.cn/downloads/CH341SER_EXE.html" target="_blank" rel="noopener" +>CH340驱动</a></li> +<li><a class="link" href="https://www.st.com/en/development-tools/stm32cubeprog.html#get-software" target="_blank" rel="noopener" +>STM32CubeProgramme(v2.4.0+)</a></li> +</ul> +<h4 id="2连接开发板">2.连接开发板 +</h4><p>首先将电脑的虚拟机和RailDriver打开,确保SFTP服务能够正常使用。(关于RailDriver配置可以查看这篇文章:<a class="link" href="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/" target="_blank" rel="noopener" +>【Linux系统开发】Ubuntu配置SFTP服务</a>)</p> +<p>当计算机本地磁盘出现一个SFTP(Y:)的网络盘符出现即代表服务能正常使用。</p> +<p>我们将开发板的usb接口连接到电脑,此时由于虚拟机会识别到设备,我们选择连接到本机</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111834424.png" +loading="lazy" +alt="image-20230411183456029" +></p> +<h4 id="3镜像烧录">3.镜像烧录 +</h4><ul> +<li> +<p>首先将开发板的拨码开关拨至“000”模式,然后再按下Reset键。</p> +</li> +<li> +<p>打开STM32CubeProgramme,选择USB设备和正确的端口后,点击Connect连接小熊派。</p> +</li> +<li> +<p>点击STM32CubeProgrammer工具的“+”按钮,然后选择烧录配置的tvs文件(路径:<code>Y:\home\bearpi\project\bearpi-hm_micro_small\applications\BearPi\BearPi-HM_Micro\tools\download_img\flashlayout\bearpi-hm_micro.tsv</code>)。</p> +</li> +<li> +<p>点击Browse按钮,然后选择工程源码下的烧录镜像路径</p> +</li> +<li> +<p>点击下载,等待烧录成功,中间会有一次断开连接,需要再虚拟机界面再次选择将USB设备连接到主机</p> +</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111935608.png" +loading="lazy" +alt="image-20230411193521444" +></p> +<h4 id="4启动系统">4.启动系统 +</h4><p>将开发板背面的拨码开关切换至“010”启动模式,并按一下RESET重启开发板,之后等待几秒中会看到屏幕中出现桌面及预装软件,之后就可以结合SSH进行远程终端开发了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111940183.jpg" +loading="lazy" +alt="3" +></p> \ No newline at end of file diff --git a/tags/harmonyos/page/1/index.html b/tags/harmonyos/page/1/index.html new file mode 100644 index 000000000..f3e88a055 --- /dev/null +++ b/tags/harmonyos/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/harmonyos/ + \ No newline at end of file diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 000000000..9f6a1f3b2 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,58 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/index.xml b/tags/index.xml new file mode 100644 index 000000000..c04153124 --- /dev/null +++ b/tags/index.xml @@ -0,0 +1 @@ +Tags on kurisaWhttps://kurisaw.github.io/tags/Recent content in Tags on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000RT-Threadhttps://kurisaw.github.io/tags/rt-thread/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/tags/rt-thread/RTduinohttps://kurisaw.github.io/tags/rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/tags/rtduino/Experience Sharinghttps://kurisaw.github.io/tags/experience-sharing/Sat, 03 Feb 2024 15:00:00 +0000https://kurisaw.github.io/tags/experience-sharing/MCUhttps://kurisaw.github.io/tags/mcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/tags/mcu/MPUhttps://kurisaw.github.io/tags/mpu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/tags/mpu/Micro_ROShttps://kurisaw.github.io/tags/micro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/micro_ros/ROS2https://kurisaw.github.io/tags/ros2/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/ros2/USBhttps://kurisaw.github.io/tags/usb/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/usb/WSLhttps://kurisaw.github.io/tags/wsl/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/wsl/CIhttps://kurisaw.github.io/tags/ci/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/ci/Githttps://kurisaw.github.io/tags/git/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/git/Linuxhttps://kurisaw.github.io/tags/linux/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/linux/Scripyhttps://kurisaw.github.io/tags/scripy/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/scripy/Ubuntuhttps://kurisaw.github.io/tags/ubuntu/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/tags/ubuntu/Sshhttps://kurisaw.github.io/tags/ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/tags/ssh/Matterhttps://kurisaw.github.io/tags/matter/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/tags/matter/Platformhttps://kurisaw.github.io/tags/platform/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/tags/platform/ESP-C3https://kurisaw.github.io/tags/esp-c3/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/tags/esp-c3/CSAhttps://kurisaw.github.io/tags/csa/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/tags/csa/BLEhttps://kurisaw.github.io/tags/ble/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/tags/ble/Nordichttps://kurisaw.github.io/tags/nordic/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/tags/nordic/Easyflashhttps://kurisaw.github.io/tags/easyflash/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/easyflash/FALhttps://kurisaw.github.io/tags/fal/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/fal/LPChttps://kurisaw.github.io/tags/lpc/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/lpc/LPC55s69https://kurisaw.github.io/tags/lpc55s69/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/lpc55s69/NXPhttps://kurisaw.github.io/tags/nxp/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/nxp/SFUDhttps://kurisaw.github.io/tags/sfud/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/sfud/BSDhttps://kurisaw.github.io/tags/bsd/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/bsd/SAL套接字https://kurisaw.github.io/tags/sal%E5%A5%97%E6%8E%A5%E5%AD%97/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/sal%E5%A5%97%E6%8E%A5%E5%AD%97/TCP/IPhttps://kurisaw.github.io/tags/tcp/ip/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/tcp/ip/UDPhttps://kurisaw.github.io/tags/udp/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/udp/Wiresharkhttps://kurisaw.github.io/tags/wireshark/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/wireshark/BearPi-HM_Microhttps://kurisaw.github.io/tags/bearpi-hm_micro/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/bearpi-hm_micro/HarmonyOShttps://kurisaw.github.io/tags/harmonyos/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/harmonyos/SFTPhttps://kurisaw.github.io/tags/sftp/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/sftp/资讯https://kurisaw.github.io/tags/%E8%B5%84%E8%AE%AF/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E8%B5%84%E8%AE%AF/KMPhttps://kurisaw.github.io/tags/kmp/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/kmp/Leetcodehttps://kurisaw.github.io/tags/leetcode/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/leetcode/双指针法https://kurisaw.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95/字符串https://kurisaw.github.io/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/数据结构https://kurisaw.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/算法https://kurisaw.github.io/tags/%E7%AE%97%E6%B3%95/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E7%AE%97%E6%B3%95/剑指offerhttps://kurisaw.github.io/tags/%E5%89%91%E6%8C%87offer/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%89%91%E6%8C%87offer/哈希表https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/哈希解法https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A7%A3%E6%B3%95/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A7%A3%E6%B3%95/哈希函数https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E5%87%BD%E6%95%B0/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E5%87%BD%E6%95%B0/哈希碰撞https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E7%A2%B0%E6%92%9E/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E7%A2%B0%E6%92%9E/线性探测法https://kurisaw.github.io/tags/%E7%BA%BF%E6%80%A7%E6%8E%A2%E6%B5%8B%E6%B3%95/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E7%BA%BF%E6%80%A7%E6%8E%A2%E6%B5%8B%E6%B3%95/链地址法https://kurisaw.github.io/tags/%E9%93%BE%E5%9C%B0%E5%9D%80%E6%B3%95/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E9%93%BE%E5%9C%B0%E5%9D%80%E6%B3%95/环形链表https://kurisaw.github.io/tags/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/链表https://kurisaw.github.io/tags/%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E9%93%BE%E8%A1%A8/递归法https://kurisaw.github.io/tags/%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E9%80%92%E5%BD%92%E6%B3%95/二分查找https://kurisaw.github.io/tags/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/数组https://kurisaw.github.io/tags/%E6%95%B0%E7%BB%84/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E6%95%B0%E7%BB%84/暴力解法https://kurisaw.github.io/tags/%E6%9A%B4%E5%8A%9B%E8%A7%A3%E6%B3%95/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E6%9A%B4%E5%8A%9B%E8%A7%A3%E6%B3%95/螺旋矩阵https://kurisaw.github.io/tags/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/MicroPythonhttps://kurisaw.github.io/tags/micropython/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/tags/micropython/D1shttps://kurisaw.github.io/tags/d1s/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/tags/d1s/RDChttps://kurisaw.github.io/tags/rdc/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/tags/rdc/Risc-Vhttps://kurisaw.github.io/tags/risc-v/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/tags/risc-v/RT-Smarthttps://kurisaw.github.io/tags/rt-smart/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/tags/rt-smart/Envhttps://kurisaw.github.io/tags/env/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/tags/env/Operating Systemhttps://kurisaw.github.io/tags/operating-system/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/tags/operating-system/Cplusplushttps://kurisaw.github.io/tags/cplusplus/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/cplusplus/多态性https://kurisaw.github.io/tags/%E5%A4%9A%E6%80%81%E6%80%A7/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E5%A4%9A%E6%80%81%E6%80%A7/封装性https://kurisaw.github.io/tags/%E5%B0%81%E8%A3%85%E6%80%A7/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E5%B0%81%E8%A3%85%E6%80%A7/抽象性https://kurisaw.github.io/tags/%E6%8A%BD%E8%B1%A1%E6%80%A7/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E6%8A%BD%E8%B1%A1%E6%80%A7/类和对象https://kurisaw.github.io/tags/%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/继承性https://kurisaw.github.io/tags/%E7%BB%A7%E6%89%BF%E6%80%A7/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E7%BB%A7%E6%89%BF%E6%80%A7/C_pointerhttps://kurisaw.github.io/tags/c_pointer/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/tags/c_pointer/C语言https://kurisaw.github.io/tags/c%E8%AF%AD%E8%A8%80/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/tags/c%E8%AF%AD%E8%A8%80/函数https://kurisaw.github.io/tags/%E5%87%BD%E6%95%B0/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E5%87%BD%E6%95%B0/指针https://kurisaw.github.io/tags/%E6%8C%87%E9%92%88/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/tags/%E6%8C%87%E9%92%88/ \ No newline at end of file diff --git a/tags/kmp/index.html b/tags/kmp/index.html new file mode 100644 index 000000000..9d5a575bd --- /dev/null +++ b/tags/kmp/index.html @@ -0,0 +1,55 @@ +Tag: KMP - kurisaW +

Tags

1 page

KMP

\ No newline at end of file diff --git a/tags/kmp/index.xml b/tags/kmp/index.xml new file mode 100644 index 000000000..cd960a0be --- /dev/null +++ b/tags/kmp/index.xml @@ -0,0 +1,658 @@ +KMP on kurisaWhttps://kurisaw.github.io/tags/kmp/Recent content in KMP on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p> \ No newline at end of file diff --git a/tags/kmp/page/1/index.html b/tags/kmp/page/1/index.html new file mode 100644 index 000000000..3cfb70b02 --- /dev/null +++ b/tags/kmp/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/kmp/ + \ No newline at end of file diff --git a/tags/leetcode/index.html b/tags/leetcode/index.html new file mode 100644 index 000000000..9c47fecfd --- /dev/null +++ b/tags/leetcode/index.html @@ -0,0 +1,56 @@ +Tag: Leetcode - kurisaW +

Tags

8 pages

Leetcode

\ No newline at end of file diff --git a/tags/leetcode/index.xml b/tags/leetcode/index.xml new file mode 100644 index 000000000..91f0f52e0 --- /dev/null +++ b/tags/leetcode/index.xml @@ -0,0 +1,5039 @@ +Leetcode on kurisaWhttps://kurisaw.github.io/tags/leetcode/Recent content in Leetcode on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git a/tags/leetcode/page/1/index.html b/tags/leetcode/page/1/index.html new file mode 100644 index 000000000..848943767 --- /dev/null +++ b/tags/leetcode/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/leetcode/ + \ No newline at end of file diff --git a/tags/leetcode/page/2/index.html b/tags/leetcode/page/2/index.html new file mode 100644 index 000000000..253167546 --- /dev/null +++ b/tags/leetcode/page/2/index.html @@ -0,0 +1,56 @@ +Tag: Leetcode - Pager 2 - kurisaW +

Tags

8 pages

Leetcode

\ No newline at end of file diff --git a/tags/linux/index.html b/tags/linux/index.html new file mode 100644 index 000000000..0e63754bb --- /dev/null +++ b/tags/linux/index.html @@ -0,0 +1,57 @@ +Tag: Linux - kurisaW +

Tags

13 pages

Linux

\ No newline at end of file diff --git a/tags/linux/index.xml b/tags/linux/index.xml new file mode 100644 index 000000000..c00f3af28 --- /dev/null +++ b/tags/linux/index.xml @@ -0,0 +1,2985 @@ +Linux on kurisaWhttps://kurisaw.github.io/tags/linux/Recent content in Linux on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Linux系统开发】Linux常见开发汇总https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover.jpg" alt="Featured image of post 【Linux系统开发】Linux常见开发汇总" /><h2 id="1vmware-tools-灰色无法点击">1.vmware tools 灰色无法点击 +</h2><p>执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get update +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get upgrade +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install open-vm-tools-desktop -y +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2linux安装搜狗输入法">2.linux安装搜狗输入法 +</h2><p>终端安装 fcitx</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install fcitx +</span></span></code></pre></td></tr></table> +</div> +</div><p>到搜狗官方下载 deb 包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://shurufa.sogou.com/linux" target="_blank" rel="noopener" +>https://shurufa.sogou.com/linux</a></li> +</ul> +</blockquote> +<p>使用linux自带的安装程序安装输入法后,安装如下输入法依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 +</span></span><span class="line"><span class="cl">sudo apt install libgsettings-qt1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启即可</p> +<h2 id="3cmake安装指定版本">3.Cmake安装指定版本 +</h2><p>首先去官网下载所需版本的压缩包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://cmake.org/files/" target="_blank" rel="noopener" +>https://cmake.org/files/</a></li> +</ul> +</blockquote> +<p>执行解压命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -zxv -f cmake-3.22.6.tar.gz +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装相关依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install g++ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install make +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入解压后的cmake文件,执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./bootstrap +</span></span></code></pre></td></tr></table> +</div> +</div><p>编译构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">make +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo make install +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4ubuntu中使用-st-link">4.ubuntu中使用 st-link +</h2><p>安装依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc +</span></span></code></pre></td></tr></table> +</div> +</div><p>依次执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># download source code</span> +</span></span><span class="line"><span class="cl">git clone https://github.com/stlink-org/stlink +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> stlink +</span></span><span class="line"><span class="cl"><span class="c1"># build</span> +</span></span><span class="line"><span class="cl">cmake . +</span></span><span class="line"><span class="cl">make +</span></span><span class="line"><span class="cl"><span class="c1"># install</span> +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bin +</span></span><span class="line"><span class="cl">sudo cp st-* /usr/local/bin +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ../lib +</span></span><span class="line"><span class="cl">sudo cp *.so* /lib32 +</span></span><span class="line"><span class="cl"><span class="c1"># add rules</span> +</span></span><span class="line"><span class="cl">sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ +</span></span><span class="line"><span class="cl">sudo udevadm control --reload-rules +</span></span><span class="line"><span class="cl">sudo udevadm trigger +</span></span></code></pre></td></tr></table> +</div> +</div><p>尝试烧录代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#check if st-link is plugged</span> +</span></span><span class="line"><span class="cl">sudo st-info --probe +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># write hex</span> +</span></span><span class="line"><span class="cl">sudo st-flash --format ihex write myapp.hex +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 一般下载一次,会失败,需要刷入两次;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># write bin</span> +</span></span><span class="line"><span class="cl">sudo st-flash write in.bin 0x8000000 <span class="c1">#stm32f4xx</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># read bin</span> +</span></span><span class="line"><span class="cl">st-flash <span class="nb">read</span> out.bin 0x8000000 0x1000 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># restart</span> +</span></span><span class="line"><span class="cl"><span class="c1"># 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作</span> +</span></span><span class="line"><span class="cl">sudo st-flash reset +</span></span></code></pre></td></tr></table> +</div> +</div><p>具体的GDB调试可以参考这篇文章:</p> +<blockquote> +<ul> +<li><a class="link" href="https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html" target="_blank" rel="noopener" +>https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html</a></li> +</ul> +</blockquote>【Linux系统开发】Ubuntu配置SFTP服务https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover.jpg" alt="Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务" /><h2 id="sftp介绍">SFTP介绍 +</h2><p>SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)</p> +<h2 id="安装步骤">安装步骤 +</h2><h4 id="1目标">1.目标: +</h4><p>在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。</p> +<h4 id="2查看ubuntu系统信息">2.查看Ubuntu系统信息 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071010234.png" +loading="lazy" +alt="image-20230407101026858" +></p> +<h4 id="3检查是否已安装sftp">3.检查是否已安装SFTP +</h4><p>在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071011398.png" +loading="lazy" +alt="image-20230407101132327" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">client</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">client</span> +</span></span><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">server</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。</p> +<h4 id="4新建用户组sftp-users并新建用户sftp">4.新建用户组SFTP-users,并新建用户SFTP +</h4><p>为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">adduser</span> <span class="nf">sftp</span> <span class="p">(</span><span class="err">这部分会让你新建用户组信息,建议最好截图保存下</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5给sftp赋权并新建用户组ssh-users">5.给SFTP赋权并新建用户组SSH-users +</h4><p>将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">G</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="nb">false</span> <span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">a</span> <span class="o">-</span><span class="n">G</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">bbc2005</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6创建并设置sftp用户目录">6.创建并设置SFTP用户目录 +</h4><p>为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chown</span> <span class="nl">yifang</span><span class="p">:</span><span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chmod</span> <span class="mi">770</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="7修改ssh配置文件">7.修改SSH配置文件 +</h4><p>在sshd_config文件的最后添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssh</span><span class="o">/</span><span class="n">sshd_config</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">AllowGroups</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">Match</span> <span class="n">Group</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">ChrootDirectory</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">AllowTcpForwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"><span class="n">X11Forwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">ForceCommand</span> <span class="n">internal</span><span class="o">-</span><span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些内容的意思是:</p> +<ul> +<li>只允许ssh-users和SFTP-users通过SSH访问系统;</li> +<li>针对SFTP-users用户,增加一些额外的设置: +<ul> +<li>将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);</li> +<li>禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。</li> +<li>如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。</li> +</ul> +</li> +</ul> +<h4 id="8sftp客户端验证">8.SFTP客户端验证 +</h4><p>首先将虚拟机重启:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">reboot</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。</p> +<p>查看ubuntu网络ip地址</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ifconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071038531.png" +loading="lazy" +alt="image-20230407103802472" +>zhe</p> +<p>这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考<a class="link" href="https://blog.devyi.com/archives/418/" target="_blank" rel="noopener" +>RaiDrive—将网盘映射为磁盘</a>)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071044734.png" +loading="lazy" +alt="image-20230407104441660" +></p> +<p>此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071046125.png" +loading="lazy" +alt="image-20230407104643007" +></p>x210开发板根目录文件系统构建https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/Thu, 28 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91x210%E5%BC%80%E5%8F%91%E6%9D%BF%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%84%E5%BB%BA/cover.jpg" alt="Featured image of post x210开发板根目录文件系统构建" /><h2 id="一开发板配置">一、开发板配置 +</h2><p>(使用secureCRT) +首先确保开发板完成以下配置:</p> +<p>主机IP: +<code>set ipaddr192.168.1.10</code> +服务器IP: +<code>set serverip 192.168.1.141</code> +网关: +<code>set gatewayip 192.168.1.1</code> +子网掩码: +<code>set netmask 255.255.255.0</code> +内核驱动设置: +<code>set bootcmd 'tftp 30008000 zImage; bootm 30008000'</code> +bootargs配置: +<code>set bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/x210_bsp ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200</code></p> +<p>最后输入save保存一下,这样开发板的网络和内核配置就设置好了</p> +<h2 id="二了解rootfs">二、了解rootfs +</h2><p>rootfs的两种表现形式: +1、nfs方式启动的文件夹形式的rootfs(主机)</p> +<p>2、用来烧录的镜像形式rootfs(开发板)</p> +<h2 id="三虚拟机文件配置">三、虚拟机文件配置 +</h2><h4 id="1目录配置">1.目录配置 +</h4><p>首先我们需要root进入超级用户模式,在虚拟机的root目录下再次创建以下两个目录: +<code>rootfs x210_bsp</code></p> +<p>这时候我们需要知道这两个文件夹下有什么:</p> +<blockquote> +<ul> +<li>x210_bsp:用于uboot烧录和配置</li> +<li>rootfs:用于挂载开发板根文件系统</li> +</ul> +</blockquote> +<h4 id="2x210_bsp配置">2.x210_bsp配置 +</h4><p>首先进入到该目录下,并将文件qt_x210v3s_160307.tar.bz2复制到该目录下解压</p> +<p><img src="https://img-blog.csdnimg.cn/b4f56856fa1447b6b49ea43313bc141a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压qt_x210v3s_160307.tar.bz2内的文件内容,后面会说到这个目录如何使用</p> +<h4 id="3rootfs配置">3.rootfs配置 +</h4><p>首先我们需要在该目录下继续创建一个名为x210_rootfs的文件夹,并且进入到该文件夹下,将我们上面提到的busybox文件复制到此目录下并解压</p> +<p><img src="https://img-blog.csdnimg.cn/87600bf5cbf44ac3a94db3bc7bd01d78.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上是解压busybox-1.24.1(这是我选择的busybox版本)的全部文件</p> +<h4 id="4make-menuconfig">4.make menuconfig +</h4><p>进入x210_bsp/kernel 目录下,输入命令:make menuconfig进入图形化菜单</p> +<blockquote> +<p>这里我们按下面操作完成网络配置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[*]Networking support ---&gt; +</span></span><span class="line"><span class="cl"> Networking options ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/a33a8e4e25bc4335b263cdbc59bd79a6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>网络文件系统设置</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">File systems ---&gt; +</span></span><span class="line"><span class="cl"> [*]Networking File Systems ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>有需要把开发板作为服务器端的也可以选择把<code>NFS server support</code>设置打开,这里我们仅实验客户端</p> +<p><img src="https://img-blog.csdnimg.cn/ce11d76876fd463db53915dffde15776.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>以上配置结束后输入命令<code>make</code>编译,至此开发板uboot的网络和文件系统部分配置结束。</p> +<h2 id="四busybox的移植实战">四、busybox的移植实战 +</h2><h4 id="1了解busybox">1、了解busybox +</h4><blockquote> +<p>busybox是一个集成了一百多个最常用linux命令和工具的软件,他甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分立式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍。</p> +</blockquote> +<h4 id="2busybox源码获取">2、busybox源码获取 +</h4><p><a class="link" href="http://www.busybox.net/" target="_blank" rel="noopener" +>busybox官网</a></p> +<p><code>注意:我们在文件系统构建中,内核编译和文件系统的程序编译都必须是使用的统一交叉编译器。(选择将虚拟机中的交叉编译文件复制一份到开发板构建的文件系统下)</code></p> +<h4 id="3busybox配置">3、busybox配置 +</h4><p>(1)修改Makefile</p> +<p>首先进入<code>~/rootfs/x210_rootfs/busybox-1.24.1</code>目录下</p> +<p>输入命令<code>vi Makefile</code>进入脚本进行以下修改</p> +<p>173行:<code>CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-</code> +<code>注意:此处的交叉编译链需要对照自己电脑的交叉编译链</code> +191行:<code>ARCH=arm</code></p> +<p><img src="https://img-blog.csdnimg.cn/988e15e86dde4807aa26011e6686bc6f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p>(2)make menuconfig配置</p> +<p>Tip:此处的图形化菜单需要ncurses库(联网下载),由于之前博主自己在这里没有很深的基础知识,走了很多弯路。 +因为后面的文件系统的挂载需要虚拟机切换网络状态为桥接模式,但是我的虚拟机桥接网络总是会反复重连,所以建议先将该库下载好,方便后续使用。</p> +<p>make menuconfig</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Settings</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="n">Build</span> <span class="n">Options</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Build</span> <span class="n">BusyBox</span> <span class="n">as</span> <span class="n">a</span> <span class="k">static</span> <span class="n">binary</span><span class="p">(</span><span class="n">no</span> <span class="n">shared</span> <span class="n">libs</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Busybox</span> <span class="n">Library</span> <span class="n">Tuning</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">vi</span><span class="o">-</span><span class="n">style</span> <span class="n">line</span> <span class="n">editing</span> <span class="n">commands</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Fancy</span> <span class="n">shell</span> <span class="n">prompts</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">Module</span> <span class="n">Utilities</span><span class="o">---&gt;</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span> <span class="p">]</span><span class="n">Simplified</span> <span class="n">modutils</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">insmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">rmmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">lsmod</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">modprobe</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">depmod</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Linux</span> <span class="n">System</span> <span class="n">Utilities</span><span class="o">---&gt;</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">mdev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">mdev</span><span class="o">.</span><span class="n">conf</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">subdirs</span><span class="o">/</span><span class="n">symlinks</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">regular</span> <span class="n">expressions</span> <span class="n">substitutions</span> <span class="n">when</span> <span class="n">renaming</span> <span class="n">dev</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">command</span> <span class="n">execution</span> <span class="n">at</span> <span class="n">device</span> <span class="n">addition</span><span class="o">/</span><span class="n">removal</span> +</span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">Support</span> <span class="n">loading</span> <span class="n">of</span> <span class="n">firmwares</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>大家学习使用的时候跟着上面的进行配置即可 +配置完成后,输入以下命令: +<code>make -j4</code> (4代表我主机的内核数) +无报错继续下一步: +make install</p> +<blockquote> +<p>解释:在Linux系统中安装软件的一般步骤:下载-配置-编译-安装,所以上面的make -j4就代表编译,make install代表安装</p> +</blockquote> +<p>(3)设置busybox安装路径</p> +<ul> +<li><code>make menuconfig</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Busybox Settings ---&gt; +</span></span><span class="line"><span class="cl"> Installation Options (&#34;make install&#34; behavior) ---&gt; +</span></span><span class="line"><span class="cl"> (./)BusyBox installation prefix) //这里设置安装路径 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cf7de167425b47acaff070d610f78d1f.png" +loading="lazy" +></p> +<p>(4)解决方案 +在虚拟机的配置中,由于代码的复杂性时常让我们不能很全面清晰的看到自己所做的改变,有时候就会出现各种各样的状况。</p> +<p>make -j4编译可能遇到的问题:</p> +<ul> +<li><code>sync.c(text.sync_main+0x78):undefined reference to 'syncfs'</code></li> +</ul> +<p><code>分析:</code>可能是gcc和当前busybox版本不兼容造成的,我们只需要将其禁用即可。</p> +<p><code>解决方法:</code></p> +<p><code>make menuconfig</code> +点击/进入搜索,输入SYNC,根据提示禁用SYNC +最后再make -j4编译一下即可</p> +<p><img src="https://img-blog.csdnimg.cn/7defb1eda80748d29c73a564f2e631be.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2b4ded5286854f1ca4e7d8fae5e148c4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<img src="https://img-blog.csdnimg.cn/932a1580f3b54a5ca685be2b7c5c1dd7.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>其实还可以选择在源代码中解决这个问题,过程有些繁琐就不赘述,动手能力强的可以一试。</p> +<p>(5)make install简述</p> +<ul> +<li>默认安装位置:./_install</li> +<li>文件包含有:bin linuxrc sbin usr</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/002a97e1448542f784b04d188f6cb7f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->ls -l可以看到: linuxrc -&gt; bin/busybox //这个linuxrc其实就是个符号链接 <!-- raw HTML omitted --></p> +<p><img src="https://img-blog.csdnimg.cn/b97a1a96e2a94503832d05c0f8ca072e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->这里也不难发现,bin下的所有的符号链接都指向了busybox<!-- raw HTML omitted --></p> +<p>(6)make menuconfig更改NFS挂载目录到/root/rootfs/x210_rootfs下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">make menuconfig +</span></span><span class="line"><span class="cl"> Busybox Settings —&gt; +</span></span><span class="line"><span class="cl"> Installation Options (“make install” behavior) —&gt; +</span></span><span class="line"><span class="cl"> (/root/rootfs/x210_rootfs)BusyBox installation prefix +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行<code>make install</code>后,回到被挂载的目录下,可以发现这四个文件已经生成。</p> +<h2 id="五nfs挂载根文件系统">五、NFS挂载根文件系统 +</h2><h4 id="1nfs简述">1.NFS简述 +</h4><ul> +<li>NFS 是Network File System的缩写,即网络文件系统。</li> +<li>功能:通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据。</li> +</ul> +<h4 id="2nfs服务器安装">2.NFS服务器安装 +</h4><p><code>sudo apt-get install nfs-kernel-server</code></p> +<h4 id="3nfs使用过程">3.NFS使用过程 +</h4><p>启动NFS服务器-&gt;启动NFS客户端-&gt;挂载NFS目录</p> +<h4 id="4nfs配置">4.NFS配置 +</h4><ul> +<li>输入命令<code>vim /etc/exports</code></li> +</ul> +<p>在最后一行修改</p> +<ul> +<li><code>&quot;文件挂载目录&quot; *(rw,sync,no_root_squash,no_subtree_check)</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a355d9b6e233404ea19531fa04947910.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>保存退出后,输入<code>mount -t nfs -o nolock 192.168.240.33:/root/rootfs/x210_rootfs</code>(根据实际情况修改)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/9383c4e9c6e74c7485d07a6aec6f99fd.png" +loading="lazy" +></p> +<ul> +<li>输入命令<code>/etc/init.d/nfs-kernel-server restart</code>重启NFS服务</li> +</ul> +<h2 id="六开发板根目录配置">六、开发板根目录配置 +</h2><p>首先将etc目录放置到挂载根目录下</p> +<p>etc目录下载:</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>点击此处</a></p> +<h4 id="1inittab文件详解">1.inittab文件详解 +</h4><p>&lt;1&gt;添加一个典型的inittab文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>inittab下载</a></p> +<p>&lt;2&gt;inittab格式解析</p> +<p><code>id:runlevels:action:process</code></p> +<p><img src="https://img-blog.csdnimg.cn/4f374d2fe1ca4f7da6f22403e314525f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>解释:</p> +<ul> +<li>id:标识符,即代表记录的名字</li> +<li>runlevels(可不填):用于指定该记录在哪些运行级别中运行,runlevel可以设定为单个运行级别,也可以设定多个运行级别</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/dd8867359c0c44c6945fc29dbf0a90a3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>action:用于描述该级别该执行什么操作(部分说明)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/99fb967e453c456b989bd57ec0e84020.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>process:具体执行的命令</li> +</ul> +<p>&lt;3&gt;了解busybox init与inittab之间的关系</p> +<ul> +<li>busybox init进程主要完成系统的初始化工作。</li> +</ul> +<p>busybox init进程的工作流程:</p> +<blockquote> +<p><!-- raw HTML omitted -->为init设置信号处理过程-&gt;初始化控制台-&gt;剖析/etc/inittab文件-&gt;执行系统初始化命令行,缺省(默认)情况下会使用/etc/init.d/rcS-&gt;执行所有导致 init 暂停的 inittab 命令(动作类型: wait)-&gt;执行所有仅执行一次的 inittab(动作类型: once)<!-- raw HTML omitted --></p> +</blockquote> +<ul> +<li>一旦完成以上工作, init 进程便会<code>循环执行</code>以下进程:</li> +</ul> +<blockquote> +<p>&lt;1&gt;执行所有终止时必须重新启动的 inittab 命令(动作类型: respawn) +&lt;2&gt;执行所有终止时必须重新启动但启动前必须询问用户的 inittab 命令(动作类型: askfirst)</p> +</blockquote> +<ul> +<li>简而言之,就是初始化控制台之后, BusyBox 会检查/etc/inittab 文件是否存在,如果此文件不存在, BusyBox 会使用缺省的inittab 配置,它主要为系统重引导,系统挂起以及 init 重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1 到 tty4)设置启动 shell 的动作。如果未建立这些设备文件, BusyBox 会报错。</li> +</ul> +<p>注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。</p> +<p>&lt;4&gt;配置 +vi命令打开inittab模板文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#first:run the system script file 注释 +</span></span><span class="line"><span class="cl">::sysinit:/etc/init.d/rcS //在控制台初始化之前执行rcS +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::askfirst:-/bin/sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">::ctrlaltdel:-/sbin/reboot //执行控制台时的打印信息 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#umount all filesystem //同时按住3键可以重启 +</span></span><span class="line"><span class="cl">::shutdown:/bin/umount -a -r//关机时接触挂载init +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#restart init process//重启时启动 +</span></span><span class="line"><span class="cl">::restart:/sbin/init +</span></span></code></pre></td></tr></table> +</div> +</div><p>修改脚本: +<img src="https://img-blog.csdnimg.cn/0ccb3db4d10c417b9eeb5526f87c7793.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rcs文件详解">2.rcS文件详解 +</h4><p>&lt;1&gt;添加一个典型的rcS文件到etc目录下</p> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85219254" target="_blank" rel="noopener" +>rcS下载</a></p> +<p>&lt;2&gt;rcS文件解析</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/sh 需要继续添加环境变量,在后面:/new 即可 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">PATH</span><span class="o">=</span>/sbin:/bin:/usr/sbin:/usr/bin +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">runlevel</span><span class="o">=</span>S +</span></span><span class="line"><span class="cl"><span class="nv">prevlevel</span><span class="o">=</span>N +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">umask</span> <span class="m">022</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> PATH runlevel prevlevel +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -a +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>PATH=xxx</li> +</ul> +<blockquote> +<p>PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。</p> +</blockquote> +<ul> +<li>runlevel=</li> +</ul> +<blockquote> +<p>linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/2c17661c32464ad8a0c96c654e622289.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<ul> +<li>umask=</li> +</ul> +<blockquote> +<p>umask是linux的一个命令,作用是设置linux系统的umask值,而umask值决定当前用户在创建文件时的默认权限。</p> +</blockquote> +<ul> +<li>mount -a</li> +</ul> +<blockquote> +<p>mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)</p> +</blockquote> +<h4 id="3rcs实战">3.rcS实战 +</h4><p>首先将前面提供的etc压缩包模板下载至共享文件夹</p> +<p>&lt;1&gt;输入命令打开rcS脚本:<code>vi etc/init.d/rcS</code>。我们可以发现在每一行代码的后面都有一个^m,将其删除,这样开发板启动的时候就不会报错了</p> +<p>&lt;2&gt;mdev</p> +<blockquote> +<p>udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。</p> +</blockquote> +<p>rcS文件中没有启动mdev的时候,ls查看/dev目录下启动后是空的;在<code>rcS</code>文件中添加以下与mdev有关的2行配置项后:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echo /sbin/mdev &gt; /proc/sys/kernel/hotplug +</span></span><span class="line"><span class="cl">mdev -s +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/d84ea4a6677a4af08741ba6c4b6db580.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>再次启动系统后发现/dev目录下生成了很多的设备驱动文件</p> +<p>&lt;3&gt;hostname</p> +<p><code>我们进入etc目录下创建一个名为sysconfig的文件夹,并在该目录下再次touch创建一个名为HOSTNAME的文件,vi命令进入可修改当前系统主机名</code></p> +<p>hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。</p> +<ul> +<li>添加profile文件(该文件在前面etc提供的模板文件有)后,即可显示用户名和hostname</li> +</ul> +<p>&lt;4&gt;ifconfig</p> +<p>(1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.240.40),这时候就可以在rcS文件中ifconfig eth0 192.168.240.40</p> +<p><img src="https://img-blog.csdnimg.cn/5842d7cc0dd94c3fbd348189e908f09b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>&lt;5&gt;mount挂载测试</p> +<p>这时候我们在secureCRT中启动开发板,可以发现还是存在一些报错,例如</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="k">var</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">tmp</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="n">mount</span><span class="p">:</span> <span class="n">mounting</span> <span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">failed</span><span class="p">:</span> <span class="n">No</span> <span class="n">such</span> <span class="n">file</span> <span class="ow">or</span> <span class="n">directory</span> +</span></span><span class="line"><span class="cl"><span class="o">......</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这是由于我们的之前创建的根目录挂载文件中没有创建这些文件,<code>输入mkdir命令在根目录依次创建即可</code>。</p> +<h2 id="七动态链接库的拷贝">七、动态链接库的拷贝 +</h2><h4 id="1静态编译链接测试">1.静态编译链接测试 +</h4><p>首先我们在开发板根目录下touch a.c文件,然后gcc编译一下它,可以发现在虚拟机中可以成功打印,但是在开发板端执行编译命令却并没有成功,这是因为在开发板中并没有交叉编译的相关文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a.c file-&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">int main() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> printf(&#34;hello world!\n&#34;); +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2解决办法">2.解决办法: +</h4><p><code>拷贝一份动态链接库文件到开发板根目录下</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp lib/*so* /root/rootfs/x210_rootfs/lib/ -rdf +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3解释">3.解释: +</h4><p><img src="https://img-blog.csdnimg.cn/6e39e3914f954ff7967b904a8aa576c5.png" +loading="lazy" +></p> +<p>这时候执行命令./a.out发现可以正常打印</p> +<h4 id="4strip工具">4.strip工具 +</h4><p>动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在<code>传统的嵌入式系统中flash空间是有限的</code>,为了<code>节省空间</code>常常把这些符号信息去掉。这样节省空间并且不影响运行。</p> +<p>去掉符号信息的命令:</p> +<p><code>arm-linux-strip *so*</code></p> +<h2 id="八ext2格式镜像烧录">八、ext2格式镜像烧录 +</h2><h4 id="1确定文件夹格式的rootfs可用">1. 确定文件夹格式的rootfs可用 +</h4><p>前面我们已经提前配置好,此处不再赘述</p> +<p><img src="https://img-blog.csdnimg.cn/560f47331e76495994c412e7f9e97425.png" +loading="lazy" +></p> +<h4 id="2ext2镜像制作">2.ext2镜像制作 +</h4><ul> +<li> +<p>首先我们在~/rootfs目录下mkdir ext2_rootfs创建用于我们的挂载目录。</p> +</li> +<li> +<p>然后输入以下命令:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">losetup /dev/loop1 rootfs.ext2 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mke2fs -m 0 /dev/loop1 10240 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">mount -t ext2 /dev/loop1 ./ext2_rootfs/ +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时我们复制一份开发板根目录到ext2_rootfs下</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cp rootfs.ext2 /mnt/hgfs/Myshare/ -f +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>进入~/rootfs目录,执行清除卸载命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">umount /dev/loop1 +</span></span><span class="line"><span class="cl">losetup -d /dev/loop1 +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>此时在rootfs目录下可以看见生成了一个rootfs.ext2镜像文件,我们将其复制到共享文件夹下,然后再将其复制到电脑<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>fastboot</a>目录下,执行uboot烧录操作,借鉴该博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a></li> +</ul> +<p>至此开发板根目录构建完成,其中也是遇到很多问题,也因此给自己挖了很多坑,然后又给自己填坑,虽然过程不尽人意,但是最后获得的都是自己的,大家在尝试这个实验的时候欢迎博客私信交流!</p> +<hr> +<p>参考资料:</p> +<ul> +<li> +<p><a class="link" href="https://blog.csdn.net/wangweijundeqq/article/details/82533485?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>Linux开发之根文件系统构建及过程详解</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010299133/article/details/93414146" target="_blank" rel="noopener" +>busybox init进程和/etc/inittab关系</a></p> +</li> +<li> +<p><a class="link" href="https://blog.csdn.net/u010311609/article/details/123137181?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165080397516782184664736%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165080397516782184664736&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-123137181.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=NFS%E6%8C%82%E8%BD%BDlinux&#43;&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>NFS-LINUX挂载实践</a></p> +</li> +</ul>Ubuntu命令查看手册https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/Mon, 25 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%9B%B4%E6%96%B0%E4%B8%AD/cover.jpg" alt="Featured image of post Ubuntu命令查看手册" /><h2 id="进程管理类">进程管理类 +</h2><p>1.top命令</p> +<blockquote> +<ul> +<li>top命令是一个常用的查看系统资源使用情况和查看占用系统资源最多的进程的命令。</li> +<li>top以列形式显示所有的进程,占最多CPU资源的进程会显示在最上面。</li> +</ul> +</blockquote> +<p>2.htop命令</p> +<blockquote> +<ul> +<li>htop命令是top的改进版。</li> +<li>默认情况下,大多数Linux发行版本都没有安装htop。</li> +<li>htop命令显示的信息与top相同,但它的界面更人性化。</li> +</ul> +</blockquote> +<p>3.pstree</p> +<blockquote> +<ul> +<li>pstree命令也可以显示进程信息。</li> +<li>它以树的形式显示进程。</li> +</ul> +</blockquote> +<p>4.kill</p> +<blockquote> +<ul> +<li>kill命令可以根据进程ID来杀死进程。</li> +<li>你可以使用ps -A,top,或者grep命令获取到进程ID。</li> +</ul> +</blockquote> +<pre><code>从技术层面来讲,kill命令可以发送任何信号给一个进程。 +你可以使用 kill -KILL [id] 或者 kill -9 [id] 来杀死顽固的进程。 +</code></pre> +<hr> +<h2 id="文件操作类基础篇">文件操作类(基础篇) +</h2><blockquote> +<p><strong>新建文件:touch</strong><br> +详细文档通过 man [command] 查看</p> +</blockquote> +<blockquote> +<p><strong>管理文件</strong></p> +</blockquote> +<ul> +<li>rm: 删除文件或目录(-r)</li> +<li>mkdir 新建目录</li> +<li>cp /home/jack/README.md /home/jack/work/ 拷贝文件或目录(-r)</li> +<li>mv 移动或重命名文件、目录</li> +</ul> +<blockquote> +<p><strong>压缩tzip文件</strong></p> +</blockquote> +<ul> +<li>zip FileName.zip DirName # 将DirName本身压缩</li> +<li>zip -r FileName.zip DirName # 压缩,递归处理,将指定目录下的所有文件和子目录一并压缩</li> +</ul> +<blockquote> +<p><strong>解压zip文件</strong></p> +</blockquote> +<ul> +<li>unzip filename</li> +</ul> +<blockquote> +<p><strong>查找含<code>spark</code>的目录、文件</strong></p> +</blockquote> +<ul> +<li>find /home/jack -name &lsquo;<em>spark</em>&rsquo;</li> +</ul> +<blockquote> +<p><strong>更改密码</strong></p> +</blockquote> +<ul> +<li>passwd</li> +</ul> +<blockquote> +<p><strong>更改文件名或移动文件位置</strong></p> +</blockquote> +<ul> +<li>语句:mv oldFileName newFileName</li> +<li>示例:我想把 aaa.txt修改为 bbb.txt示例语句:mv aaa.txt bbb.txt</li> +</ul> +<blockquote> +<p><strong>删除文件</strong></p> +</blockquote> +<ul> +<li>删除文件: rm test.txt</li> +<li>删除空文件夹: rmdir test</li> +<li>删除非空文件夹及其目录下的所有文件夹及文件:rm -r test</li> +<li>删除 除某个文件或文件夹之外的所有文件以及文件夹:rm -r (文件名称或文件夹名称)括号里可以放多个,用 | 分开,如rm -r (test | test.txt)</li> +</ul> +<h2 id="防火墙状态">防火墙状态 +</h2><p>首先需要输入安装命令: +<code>apt install ufw</code></p> +<blockquote> +<p>查看防火墙当前状态 +<code>sudo ufw status</code></p> +</blockquote> +<blockquote> +<p>开启防火墙 +<code>sudo ufw enable</code></p> +</blockquote> +<blockquote> +<p>关闭防火墙 +<code>sudo ufw disable</code></p> +</blockquote> +<blockquote> +<p>查看防火墙版本 +<code>sudo ufw version</code></p> +</blockquote> +<blockquote> +<p>默认允许外部访问本机 +<code>sudo ufw default allow</code></p> +</blockquote> +<blockquote> +<p>默认拒绝外部访问主机 +<code>sudo ufw default deny</code></p> +</blockquote> +<blockquote> +<p>允许外部访问443端口 +<code>sudo ufw allow 443</code></p> +</blockquote> +<blockquote> +<p>拒绝外部访问443端口 +<code>sudo ufw deny 443</code></p> +</blockquote> +<blockquote> +<p>允许某个IP地址访问本机所有端口 +<code>sudo ufw allow from 192.168.0.1</code></p> +</blockquote> +<h2 id="网络设置">网络设置 +</h2><blockquote> +<p>重置网卡 +sudo /etc/init.d/networking restart</p> +</blockquote>Study210利用SD运行流水灯程序https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%88%A9%E7%94%A8sd%E8%BF%90%E8%A1%8C%E6%B5%81%E6%B0%B4%E7%81%AF%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post Study210利用SD运行流水灯程序" /><h2 id="1安装ecilpse">1.安装ecilpse +</h2><h4 id="1确认自己的pc机开发环境开发板光盘中有如下四个eclipse包">(1)确认自己的PC机开发环境。开发板光盘中有如下四个eclipse包: +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_32.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-windows-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_64.7z +</span></span><span class="line"><span class="cl">eclipse-kepler-for-arm-gtk-linux-x86_32.7z +</span></span></code></pre></td></tr></table> +</div> +</div><p>选择自己需求对应的安装包下载解压即可(<a class="link" href="https://download.csdn.net/download/qq_56914146/85162554" target="_blank" rel="noopener" +>此处可点击下载</a>)</p> +<h4 id="2配置好eclipse的环境变量">(2)配置好eclipse的环境变量 +</h4><p>借鉴<a class="link" href="https://blog.csdn.net/m0_46165586/article/details/107296429?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165018384616781685349830%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=165018384616781685349830&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107296429.142%5ev9%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=eclipse%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>Eclipse环境变量配置-超详细</a></p> +<h2 id="2开始工程的创建">2.开始工程的创建 +</h2><h4 id="1首先双击eclipseexe文件进入初次进入需要选择一个存储位置作为工程存放处workplace">(1)首先双击eclipse.exe文件进入,初次进入需要选择一个存储位置作为工程存放处(workplace) +</h4><h4 id="2建一个流水灯工程">(2)建一个流水灯工程 +</h4><p>首先在Project Explorer的空白栏右键单击-&gt;New-&gt;C Project +<img src="https://img-blog.csdnimg.cn/0b37eba37269446faf5de58793963da2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +项目名称填写LED_test +<img src="https://img-blog.csdnimg.cn/0b7cce5b3fa341f98792a316a1937054.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +点击next,finish</p> +<p>找到我们的项目工程示例,将全部文件复制到剪贴板 +<img src="https://img-blog.csdnimg.cn/2bbe14f0a69a46fe8328ce92f1492421.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键选择paste,选择粘贴全部 +<img src="https://img-blog.csdnimg.cn/842db416ea2c4929ac655d29bc4bfb07.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +这是粘贴好的文件项目 +<img src="https://img-blog.csdnimg.cn/d1dae4dddaf346b1be377c674fefdd35.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +工程右键Build Project或直接CTRL+B编译 +<img src="https://img-blog.csdnimg.cn/9389ca0a332143fdbfb650e41fb84f2b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +此时回到我们存放工程的workplace文件目录下,可以发现生成了output文件目录 +<img src="https://img-blog.csdnimg.cn/776361da8d1045c3a39af79804bf0320.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +进入该目录下,可以发现生成了led.bin映像文件 +<img src="https://img-blog.csdnimg.cn/e497619b0ab74765aaffd33dc55be299.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="3下载源码到sd卡">3.下载源码到SD卡 +</h2><p>打开SD卡烧写工具,将上面生成的映像文件下载到SD卡 +<img src="https://img-blog.csdnimg.cn/07008c13a27e41bebc960a47747c2283.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="4实例演示">4.实例演示 +</h2><h4 id="1清除开发板中的bootloader">(1)清除开发板中的bootloader +</h4><p>由于S5PV210芯片无法直接从SD2通道启动,首先会从SD0通道启动,而SD0通道接了emmc芯片,因此我们务必将emmc中已存在的bootloader破坏掉!(关于Windows下破坏板载BootLoader方法可借鉴<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124204098?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Linux系统开发】Study210开发板刷安卓系统</a>)</p> +<h4 id="2通过sd卡运行裸机程序">(2)通过SD卡运行裸机程序 +</h4><p>将烧有裸机程序的SD卡插到Study210开发板上,长按POWER键,约3秒后即可松手,这时可以发现,四盏LED灯已经在来回闪烁了。 +<img src="https://img-blog.csdnimg.cn/ddcba636b89841629cc4eba87b6a90b2.gif" +loading="lazy" +alt="在这里插入图片描述" +></p>Study210开发板刷安卓系统https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/Sat, 23 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91study210%E5%BC%80%E5%8F%91%E6%9D%BF%E5%88%B7%E5%AE%89%E5%8D%93%E7%B3%BB%E7%BB%9F/cover.jpg" alt="Featured image of post Study210开发板刷安卓系统" /><h2 id="一破坏bootloader">一、破坏BootLoader +</h2><blockquote> +<p>1.用USB转串口线连接电脑与开发板,打开SecureCRT串口监视软件(此步骤注意:开发板上使用UART2)</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/c79baf4eb1e949c88d6bb50c32862354.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>2.长按开发板POWER按键开机,进入控制台。(让secureCRT读完全部信息)</p> +</blockquote> +<blockquote> +<p>3.输入root(password:123456)</p> +</blockquote> +<blockquote> +<p>4.然后输入<code>busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync</code></p> +</blockquote> +<blockquote> +<p>5.回车后显示</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">1+0 records in +</span></span><span class="line"><span class="cl">1+O records out +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>6.然后再输入 sync 命令 ,此时第1扇区已经破坏。 +此时重新启动开发板就无法启动了</p> +</blockquote> +<h2 id="二sd卡刷机烧录uboot到sd卡中">二、SD卡刷机(烧录uboot到SD卡中) +</h2><blockquote> +<p>1.将SD卡插入到电脑的SD卡槽,使用SD卡烧录工具x210_Fusing_Tool 进行烧录。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/958a8cf2a0554edd8e2d53d021490d4e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><!-- raw HTML omitted -->此处如果SD烧写不成功,可尝试用管理员身份运行。 +<code>插卡后,此软件会自动识别,然后在自己的电脑里选择一个uboot.bin文件。然后点击START.</code></p> +<blockquote> +<p>2.完成后将SD卡插入开发板的SD卡槽。然后开机就可以进入uboot界面了。在uboot开机自动启动倒数3秒之内迅速按下电脑回车键,打断自动启动。(否则会自动启动iNand中的android)</p> +</blockquote> +<h2 id="三fastboot-下载安装镜像">三、fastboot 下载安装镜像 +</h2><blockquote> +<p>1.用USB线的USB口 连接电脑,另一端连接开发板的OTG口,然后在SecureCRT 的uboot控制台输入fastboot命令,这时电脑会识别USB硬件,然后需要安装驱动。</p> +</blockquote> +<blockquote> +<p>2.然后将电脑内的fastboot压缩包解压到一个容易找到的文件目录下,如 D盘。打开windows控制台进入到相应目录下。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/bc1cb6ad4904482baaad59e05da074bc.png" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wex7LBk8-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415202849623.png)\]" +></p> +<blockquote> +<p>3.下一步 在fastboot文件夹下,新建一个文件夹存放要烧录的文件,如Android</p> +</blockquote> +<blockquote> +<p><code>fastboot目录下应该包含的文件</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/850cde9ff40e4109a2b46cd186f93418.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p><code> Android中应该包含的文件(由于这里我烧写的是安卓系统)</code></p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d97c6282c3ba46aba3a44b34a72e99a4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3DezB8H-1650028395333)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203108592.png)\]" +></p> +<blockquote> +<p>4.进行内核和系统的烧写 ,具体代码如下:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/eb401fcf50ec4f228025341cfcb28fca.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Dhso3IG-1650028395334)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415203639928.png)\]" +></p> +<blockquote> +<p>同时在SecureCRT下可以看到下载结果</p> +</blockquote> +<blockquote> +<p>5.最后在windows控制台下输入<code> fastboot reboot</code>命令重启系统即可。</p> +</blockquote> +<h2 id="四dnw-刷机用fastboot刷android-">四、dnw 刷机(用fastboot刷Android ) +</h2><ul> +<li>准备事项:已安装好相应的驱动、串口线(连接的是UART2)和USB已经接好,dnw已打开。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/763acfc49ae34659b891a95ccd3de444.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaxHZTvW-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415204109660.png)\]" +></p> +<p>注意:</p> +<p>(1)安装<code>SecBulk.sys Njsmodi 2416 dnw drive</code>的驱动程序在<code>\X210V3S_A\tools\USB驱动\dnw_driver</code>下,安装驱动需要禁用数字签名(可参考<a class="link" href="https://blog.csdn.net/m0_37182543/article/details/80541418?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165002148616780271549615%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=165002148616780271549615&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-80541418.142%5ev9%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=Windows%E7%A6%81%E7%94%A8%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>win10如何永久关闭数字签名</a>)</p> +<p>(2)在使用dnw过程中需要长按电源键,否则会断开连接。</p> +<p>刷机步骤:</p> +<blockquote> +<p>1.将拨码开关拨到USB启动位置。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/51ddaa8b66494111899de8774b695007.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rua1zZN3-1650028395335)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220415205448252.png)\]" +></p> +<blockquote> +<p>2.按住开机键(长按不放),DNW 配置下载地址为0xd0020010 ,然后transmit x210_usb.bin</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/63fbc995f8ab4752945842db148ad6a5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/170c0ec22ea4421daa7952994fdd3b0d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/e08d1f32d26d4558b078f85db271eab4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +></p> +<blockquote> +<p>3.(<code>同上操作</code>)DNW 修改下载地址为 0x23e00000 ,下载uboot.bin</p> +</blockquote> +<blockquote> +<p><code> 注意!!!</code>:下载的同时要看<code>SecureCRT界面</code>,串口终端有信息打印出来,在3s倒计时内按下回车键,进入shell界面。</p> +</blockquote> +<blockquote> +<p>4.回到secureCRT</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入fdisk -c 0 (进行分区) +</span></span><span class="line"><span class="cl">输入fastboot (查看分区) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>5.cmd打开系统终端,切换到fastboot目录分别执行下列红框的命令:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/7676539a597a42d38993936ee760236a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +> +<code>最后再输入</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fastboot -w +</span></span></code></pre></td></tr></table> +</div> +</div><p>全部执行完成后,将拨码开关切换回原来的状态,重新启动,此次刷机完成。</p> +<p><img src="https://img-blog.csdnimg.cn/2982435176bb485abd152c2ab508d2cc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p>此文章参考于<a class="link" href="https://blog.csdn.net/madao1234/article/details/101104872" target="_blank" rel="noopener" +>S5PV210 Study210开发板刷系统</a></p>ifconfig不显示ip地址https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ifconfig%E4%B8%8D%E6%98%BE%E7%A4%BAip%E5%9C%B0%E5%9D%80/cover.jpg" alt="Featured image of post ifconfig不显示ip地址" /><h4 id="ubuntu终端下命令ifconfig的问题解决">ubuntu终端下命令ifconfig的问题解决 +</h4><blockquote> +<p>问题一. ifconfig之后只显示lo,没有看到eth0 +问题二. ifconfig之后显示eth0,但是没有显示静态IP地址,即无inet、地址、广播、掩码。 +问题三. ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<h4 id="问题一ifconfig之后只显示lo没有看到eth0-">问题一:ifconfig之后只显示lo,没有看到eth0 ? +</h4><blockquote> +<p>1.eth0设置不正确,导致无法正常启动,修改eth0配置文件就好 +ubuntu 12.04的网络设置文件是/etc/network/interfaces,打开文件,会看到auto lo iface lo inet loopback +这边的设置是本地回路。在后面加上</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">iface eth0 inet static +</span></span><span class="line"><span class="cl">address 192.168.1.230 //(ip地址) +</span></span><span class="line"><span class="cl">netmask 255.255.255.0 //(子网掩码) +</span></span><span class="line"><span class="cl">gateway 192.168.1.1 //(网关) +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>其中eth0就是电脑的网卡,如果电脑有多块网卡,比如还会有eth1,都可以在这里进行设置。iface eth0 inet 设置为dhcp是动态获取IP,设置为static则用自定义的IP。这边要自定义IP地址,所以选择static选项。</p> +</blockquote> +<blockquote> +<p>2.eth0被关了 +输入命令行:ifconfig eth0 up #开启eth0</p> +</blockquote> +<hr> +<h4 id="问题二ifconfig之后显示eth0但是没有显示inet地址广播掩码-">问题二:ifconfig之后显示eth0,但是没有显示“inet/地址/广播/掩码/ ”? +</h4><blockquote> +<p>1.先用sudo dhclient eth0更新IP地址 +2.然后运行sudo ifconfig eth0 +3.reboot</p> +</blockquote> +<hr> +<h4 id="问题三重启后ping命令不能使用因为dns还没设置编辑etcresolvconf加上dns服务器地址">问题三:重启后,ping命令不能使用,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。 +</h4><blockquote> +<p>设置好后,如果直接ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>会发现ping不通,因为dns还没设置,编辑/etc/resolv.conf,加上dns服务器地址。</p> +</blockquote> +<pre><code>nameserver 8.8.8.8 +nameserver 8.8.4.4 +</code></pre> +<blockquote> +<p>这两个是Google提供的免费DNS服务器的IP地址</p> +</blockquote>x210开发板 虚拟驱动创建流程https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91-x210%E5%BC%80%E5%8F%91%E6%9D%BF-%E8%99%9A%E6%8B%9F%E9%A9%B1%E5%8A%A8%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B%E9%A9%B1%E5%8A%A8%E7%BC%96%E8%AF%91%E8%BF%9B%E5%86%85%E6%A0%B8/cover.jpg" alt="Featured image of post x210开发板 虚拟驱动创建流程" /><h2 id="内核编译常用命令">内核编译常用命令 +</h2><p>安装模块 +<code>lsmod module_test.ko</code> +创建设备文件 +<code>mknod /dev/test c 250 0</code> +查看设备状态 +<code>lsmod module_test.ko</code> +查看设备注册信息(分为字符设备和块设备) +<code>cat /proc/devices</code></p> +<h2 id="知识补充">知识补充: +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span><span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="n">j</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:这里如果没有指定i值,则打印出来的是随机值 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 如果定义一个静态变量而没有赋值,则打印默认为0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="虚拟驱动创建流程">虚拟驱动创建流程 +</h2><p>首先进入x210_bsp/kernel</p> +<p>make menuconfig</p> +<p><img src="https://img-blog.csdnimg.cn/783c09aa06cb4a83a4df08d76d31c447.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/dc736c9d0d2b4ceaaaffcd6f90a1a16a.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/1193fb6e02be4c52a1d5951b0236ff38.png" +loading="lazy" +></p> +<p>make -j4</p> +<p>cp arch/arm/boot/zImage /tftpboot/ -f</p> +<p>重启开发板查看开发板设备</p> +<p>ls /sys/devices/platform/</p> +<p><img src="https://img-blog.csdnimg.cn/f57e4a58658e4380967bbfa1c0813864.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/2f3b1acd43e740e68774ecbe2824ea2f.png" +loading="lazy" +></p> +<p>cd sys/class/leds</p> +<p>led_test_4编写完成后</p> +<p>编译不报错即可</p> +<p>cd /root/x210_bsp/kernel/drivers/leds/</p> +<p>cp /mnt/hgfs/Myshare/driver/led_test_4/leds-s5pv210.c ./</p> +<p>vi Makefile-&gt;</p> +<p><code>obj-$(CONFIG_LEDS_S5PV210) += leds-s5pv210.o</code></p> +<p><img src="https://img-blog.csdnimg.cn/b30ce84418064d24a4e01c96218834f2.png" +loading="lazy" +></p> +<p>vi Kconfig更改依赖(添加以下文件)</p> +<p><code>config LEDS_S5PV210 tristate &quot;LED Support for S5PV210&quot; help This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC.</code></p> +<p><img src="https://img-blog.csdnimg.cn/43715e94bbcb4e8ab850492c919afc33.png" +loading="lazy" +></p> +<p>进入到x210_bsp/kernel</p> +<p>执行make menuconfig</p> +<p>可以发现生成了新的配置(Device Drivers-&gt; LED_Support),使能这个</p> +<p><img src="https://img-blog.csdnimg.cn/31b19678d8204209b05d62de54afd1d9.png" +loading="lazy" +></p> +<p>执行make编译</p> +<p><code> cp arch/arm/boot/zImage /tftpboot/ -f</code></p> +<p>secureCRT:</p> +<p>cd sys/class/leds</p> +<p>进入LED1,执行</p> +<p>echo 1 &gt; brightness // 灯亮</p> +<p>echo 0 &gt; brightness //灯灭</p> +<hr> +<p>最后附上源代码:</p> +<p><code>leds-s5pv210.c</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/module.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/init.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/fs.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/uaccess.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio-bank.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/regs-gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/ioport.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;asm/io.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/cdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/device.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;mach/gpio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;linux/leds.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED1 S5PV210_GPJ0(3) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED2 S5PV210_GPJ0(4) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define GPIO_LED3 S5PV210_GPJ0(5) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_OFF 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define X210_LED_ON 0 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">led_classdev</span> <span class="n">mydev3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led1_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led1_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led2_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led2_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">s5pv210_led3_set</span><span class="p">(</span><span class="k">struct</span> <span class="n">led_classdev</span> <span class="o">*</span><span class="n">led_cdev</span><span class="p">,</span><span class="k">enum</span> <span class="n">led_brightness</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">&#34;s5pv210_led3_set</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">LED_OFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_OFF</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_set_value</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">,</span><span class="n">X210_LED_ON</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">s5pv210_led_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 申请GPIO +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="nf">gpio_request</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="s">&#34;led1_gpj0.3&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;gpio_request failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_direction_output</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led1&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev1</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led1_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led2&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev2</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led2_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;led3&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">mydev3</span><span class="p">.</span><span class="n">brightness_set</span> <span class="o">=</span> <span class="n">s5pv210_led3_set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">led_classdev_register</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="n">KERN_ERR</span> <span class="s">&#34;led_classdev_register failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">s5pv210_led_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">led_classdev_unregister</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mydev3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">gpio_free</span><span class="p">(</span><span class="n">GPIO_LED3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">module_init</span><span class="p">(</span><span class="n">s5pv210_led_init</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">module_exit</span><span class="p">(</span><span class="n">s5pv210_led_exit</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_LICENSE</span><span class="p">(</span><span class="s">&#34;GPL&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_AUTHOR</span><span class="p">(</span><span class="s">&#34;WYQ&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="nf">MODULE_DESCRIPTION</span><span class="p">(</span><span class="s">&#34;module_test&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>Makefile</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#KERN_VER = $(shell uname -r) +</span></span></span><span class="line"><span class="cl"><span class="cp">#KERN_DIR = /lib/modules/$(KERN_VER)/build +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">KERN_DIR</span> <span class="o">=</span> <span class="o">/</span><span class="n">root</span><span class="o">/</span><span class="n">x210_bsp</span><span class="o">/</span><span class="n">kernel</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">obj</span><span class="o">-</span><span class="n">m</span> <span class="o">+=</span> <span class="n">leds</span><span class="o">-</span><span class="n">s5pv210</span><span class="p">.</span><span class="n">o</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">all</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nl">PHONY</span><span class="p">:</span><span class="n">clean</span> +</span></span><span class="line"><span class="cl"><span class="nl">clean</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">make</span> <span class="o">-</span><span class="n">C</span> <span class="err">$</span><span class="p">(</span><span class="n">KERN_DIR</span><span class="p">)</span> <span class="n">M</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span> <span class="n">modules</span> <span class="n">clean</span> +</span></span></code></pre></td></tr></table> +</div> +</div>ubuntu彻底删除通过apt方式安装的程序https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/<img src="https://kurisaw.github.io/p/ubuntu%E5%BD%BB%E5%BA%95%E5%88%A0%E9%99%A4%E9%80%9A%E8%BF%87apt%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F/cover.jpg" alt="Featured image of post ubuntu彻底删除通过apt方式安装的程序" /><p>以删除apache2为例,其它程序也都是这么删&hellip;<br> +1.先通过apt删除程序和相关配置文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>2.自动删除不使用的软件包</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get autoremove +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.找出与apache2相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dpkg --get-selections|grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>没有就不显示,如果有就删除这些相关的程序</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get --purge remove xxx +</span></span></code></pre></td></tr></table> +</div> +</div><p>4.查看apache2是否还有进程存在</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ps -ef |grep apache2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果有就杀掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo kill -9 8888 //后面接pid号码,用空格隔开 +</span></span></code></pre></td></tr></table> +</div> +</div><p>5.全局查找和apache2相关的文件,需要一定时间,稍等</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo find / -name apache2* +</span></span></code></pre></td></tr></table> +</div> +</div><p>将找到的文件逐个删掉</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo rm -rf /usr/share/bash-completion/completions/apache2ctl +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就彻底删除掉apache2了</p>ubuntu安装交叉编译工具链https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E9%93%BE/cover.jpg" alt="Featured image of post ubuntu安装交叉编译工具链" /><h1 id="ubuntu安装交叉编译工具链附避坑指南">ubuntu安装交叉编译工具链(附避坑指南) +</h1><blockquote> +<p>1.打开Ubuntu,在终端进入/usr/local/目录下</p> +</blockquote> +<pre><code>cd /usr/local/ +</code></pre> +<blockquote> +<p>2.在local/目录下创建一个名为arm的文件夹</p> +</blockquote> +<pre><code>mkdir arm +</code></pre> +<blockquote> +<p>3.在自己的共享文件夹下找到<a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a>,并复制到之前创建的arm目录下</p> +</blockquote> +<pre><code>cp /mnt/hgfs/Myshare/arm-2009q3.tar.bz2 /usr/local/arm/ +</code></pre> +<blockquote> +<p>4.进入到arm目录下,解压该其中文件</p> +</blockquote> +<pre><code>cd /usr/local/arm +tar -jxvf arm-2009q3.tar.bz2 +</code></pre> +<blockquote> +<p>5.然后执行:</p> +</blockquote> +<pre><code>cd arm-2009q3/bin +./arm-none-linux-gnueabi-gcc -v +</code></pre> +<p><code>注意:</code><!-- raw HTML omitted -->这里如果输入<code>./arm-none-linux-gnueabi-gcc -v</code>终端显示 ‘没有这样的文件存在’ ,这是因为在64位的系统下安装32位交叉编译工具链,会无法使用,所以我们需要安装32位库的支持</p> +<pre><code>sudo apt-get install libc6:i386 +</code></pre> +<p><!-- raw HTML omitted -->安装好了之后重新输入<code>./arm-none-linux-gnueabi-gcc -v</code> +<img src="https://img-blog.csdnimg.cn/b0660902aed64a88a257ed92b892b8f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<!-- raw HTML omitted -->操作成功!</p> +<blockquote> +<p>6.为了能让它其他目录中也可以这么操作,我们把它导出到环境变量中 +打开配置文件</p> +</blockquote> +<pre><code>sudo vim /etc/profile +</code></pre> +<blockquote> +<p>7.在vi界面末尾处加入</p> +</blockquote> +<pre><code>export PATH=$PATH:/usr/local/arm/arm-2009q3/bin +</code></pre> +<blockquote> +<p>8.回到主目录,查看交叉编译工具是否可用</p> +</blockquote> +<pre><code>cd ~ +source /etc/profile +</code></pre> +<p><code>注</code> <!-- raw HTML omitted -->这里如果没有出现相关信息,切换root用户再次输入命令</p> +<p>使用 <code>echo $PATH</code>查看交叉编译链的安装路径是否加入了环境变量。 +使用<code>arm-linux-gnueabihf-gcc -v</code>测试交叉编译链是否好使</p> +<blockquote> +<p>9.建立一个符号链接,进入到/usr/local/arm/arm-2009q3/bin#目录下,vi新建一个[mk-arm-linux-.sh]脚本(文章最后可复制粘贴该脚本),然后输入命令:</p> +</blockquote> +<pre><code>chmod 777 mk-arm-linux-.sh +./mk-arm-linux-.sh +</code></pre> +<p><code>这里由于运行时报错,原因详见</code><a class="link" href="https://blog.csdn.net/LWJdear/article/details/79868551?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=bash:%20./mk-arm-linux-.sh:%20Perm&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-79868551.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>解决linux的-bash: ./xx.sh: Permission denied</a></p> +<blockquote> +<p>ls查看,可以发现符号链接出现,到此,交叉编译链配置成功!</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/6dc86a581621467d8639643cc154877a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<p><code>附件</code>:</p> +<ul> +<li> +<p><a class="link" href="https://download.csdn.net/download/qq_56914146/85094381" target="_blank" rel="noopener" +>arm-2009q3.tar.bz2</a></p> +</li> +<li> +<p><code>mk-arm-linux-.sh脚本文件</code></p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ar -s arm-linux-ar +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-as -s arm-linux-as +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++ -s arm-linux-c++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-g++ -s arm-linux-g++ +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1 +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ld -s arm-linux-ld +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-nm -s arm-linux-nm +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-size -s arm-linux-size +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strings -s arm-linux-strings +</span></span><span class="line"><span class="cl">ln arm-none-linux-gnueabi-strip -s arm-linux-strip +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<p><code>有问题欢迎评论留言致信:</code><a class="link" href="https://blog.csdn.net/qq_56914146?type=blog" target="_blank" rel="noopener" +>blogs</a></p>ubuntu桌面恢复(20.04)https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/<img src="https://kurisaw.github.io/p/ubuntu%E6%A1%8C%E9%9D%A2%E6%81%A2%E5%A4%8D20.04/cover.jpg" alt="Featured image of post ubuntu桌面恢复(20.04)" /><h3 id="恢复ubuntu2004默认桌面管理器">恢复ubuntu20.04默认桌面管理器 +</h3><ul> +<li> +<ul> +<li> +<ul> +<li><a class="link" href="#GDM_KDM_LightDM_SDDM_5" >一、GDM, KDM, LightDM, SDDM的区别和安装配置</a></li> +<li> +<ul> +<li><a class="link" href="#1GDMgnome_8" >1、GDM,gnome系列的图形管理器</a></li> +<li><a class="link" href="#2KDMSDDMKDE_17" >2、KDM,SDDM是KDE系列的图形管理器</a></li> +<li><a class="link" href="#3LightDM_27" >3、LightDM</a></li> +</ul> +</li> +<li><a class="link" href="#_37" >二、配置和切换</a></li> +<li><a class="link" href="#ubuntu2004_62" >三、恢复ubuntu20.04默认桌面管理器</a></li> +<li> +<ul> +<li><a class="link" href="#1_65" >1、打开终端,用管理员口令下载相关资源</a></li> +<li><a class="link" href="#2gnomeshell_71" >2、安装gnome-shell</a></li> +<li><a class="link" href="#3ubuntugnomedesktop_80" >3、安装ubuntu-gnome-desktop</a></li> +<li><a class="link" href="#4unitytweaktoolgnometweaktool_85" >4、安装unity-tweak-tool和gnome-tweak-tool</a></li> +<li><a class="link" href="#5_94" >5、安装完成后重启</a></li> +</ul> +</li> +</ul> +</li> +</ul> +</li> +</ul> +<p>起因:我是一个windows重度用户,实验室配置了Ubuntu服务器,我试图用远程桌面控制控制服务器的桌面。由于对Linux一窍不通,一顿乱改。结果虽然能<a class="link" href="https://blog.csdn.net/irober/article/details/112608610" target="_blank" rel="noopener" +>远程控制桌面</a>了,可是原有的显示管理器被我更改了。原先跑的好好的深度学习代码也不能跑了,原先的桌面风格(<strong>gnome图形管理器</strong>)也变成了我不喜欢的风格(<strong>轻量级的LightDM</strong>)了,大家以后要慎重。<br> +注意:我是个半吊子,仅供参考。</p> +<h3 id="一gdm-kdm-lightdm-sddm的区别和安装配置">一、GDM, KDM, LightDM, SDDM的区别和安装配置 +</h3><p><a class="link" href="https://blog.csdn.net/u014466109/article/details/105572470" target="_blank" rel="noopener" +>GDM, KDM, LightDM, SDDM的区别和安装配置</a><br> +<strong>gdm3,kdm 和 lightdm</strong> 都是显示管理器。 它们提供图形化登录并处理用户身份验证。</p> +<h4 id="1gdmgnome系列的图形管理器">1、GDM,gnome系列的图形管理器 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2kdmsddm是kde系列的图形管理器">2、KDM,SDDM是KDE系列的图形管理器 +</h4><p>kdm 是kde管理器的显示。 但在KDE5中,它被否决为 SDDM,它更适合作为显示管理器,因此在默认情况下,它是在屏幕。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">sddm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3lightdm">3、LightDM +</h4><p>LightDM用于显示管理器的规范解决方案。 它应该是轻量级的,默认情况下是 Ubuntu。Xubuntu和 Lubuntu。 它是可以配置的,有多种欢迎主题可用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">remove</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="二配置和切换">二、配置和切换 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">gdm3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在上述命令中使用管理器的名字代替 gdm3,可在它们之间进行选择。 必须重新启动才生效。</p> +<p>要检查当前正在使用的显示管理器,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cat</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">X11</span><span class="o">/</span><span class="n">default</span><span class="o">-</span><span class="n">display</span><span class="o">-</span><span class="n">manager</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>Lightdm,gdm3和KDM都是针对linux的图形化登录。 Lightdm是Ubuntu的默认版本。 要在显示管理器之间进行 switch,请使用以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">dpkg</span><span class="o">-</span><span class="n">reconfigure</span> <span class="n">lightdm</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>GDM(GNOME Display Manager),LightDM(Light Display Manager) 和 KDM(KDE Display Manager) 是为不同版本的Ubuntu配置的管理器。 他们帮助启动X 服务器。用户会话和欢迎( 登录屏幕)。 你可以运行 sudo dpkg-reconfigure gdm 以在 lightdm。gdm和KDM之间进行更改。 安装它们就像 sudo apt-get install ( 显示manger将被 kdm,gdm 和 lightdm 替换。</p> +<h3 id="三恢复ubuntu2004默认桌面管理器">三、恢复ubuntu20.04默认桌面管理器 +</h3><p><a class="link" href="https://www.zhihu.com/tardis/sogou/art/27659651" target="_blank" rel="noopener" +>恢复ubuntu20.04默认桌面管理器</a><br> +目前Ubuntu的主流桌面<strong>GNOME</strong>, Ubntu的内置桌面是<strong>Untiy</strong></p> +<h4 id="1打开终端用管理员口令下载相关资源">1、打开终端,用管理员口令下载相关资源 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">Ctrl</span><span class="o">+</span><span class="n">Alt</span><span class="o">+</span><span class="n">T</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开终端,用管理员口令下载相关资源</p> +<h4 id="2安装gnome-shell">2、安装gnome-shell +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">shell</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<p>管理员权限需要输入密码,但是系统不会显示你输入的密码<br> +输入完成后,直接回车即可</p> +<h4 id="3安装ubuntu-gnome-desktop">3、安装ubuntu-gnome-desktop +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">ubuntu</span><span class="o">-</span><span class="n">gnome</span><span class="o">-</span><span class="n">desktop</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4安装unity-tweak-tool和gnome-tweak-tool">4、安装unity-tweak-tool和gnome-tweak-tool +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">unity</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">gnome</span><span class="o">-</span><span class="n">tweak</span><span class="o">-</span><span class="n">tool</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5安装完成后重启">5、安装完成后重启 +</h4><p>然后一切恢复如初,仿佛没发生过。</p>x11vnc安装与配置https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/<img src="https://kurisaw.github.io/p/x11vnc%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/cover.jpg" alt="Featured image of post x11vnc安装与配置" /><h1 id="1-安装x11vnc">1. 安装x11vnc +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install x11vnc -y +</span></span></code></pre></td></tr></table> +</div> +</div><p>直接安装成功。</p> +<h1 id="2-设置vnc密码">2. 设置vnc密码 +</h1><p>密码存储在/etc/目录里面</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo x11vnc -storepasswd /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><p>放在这个位置,需要设置文件读取权限<br> +否则会提示密码校验失败</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/x11vnc.pass +</span></span></code></pre></td></tr></table> +</div> +</div><h1 id="3创建vnc配置文件">3.创建vnc配置文件 +</h1><p>在/etc/init 下创建一个x11vnc.conf的文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> <span class="nb">cd</span> /etc/init +</span></span><span class="line"><span class="cl"> sudo gedit x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>文件内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#description &#34;xiaoqiang vnc server&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#start on runlevel [2345]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#stop on runlevel [06]</span> +</span></span><span class="line"><span class="cl"><span class="c1">#script</span> +</span></span><span class="line"><span class="cl"> <span class="nb">exec</span> /usr/bin/x11vnc -auth guess -capslock -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport <span class="m">5900</span> -shared +</span></span><span class="line"><span class="cl"><span class="c1">#end script</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>我的密码创建在/etc目录下,可以直接复制这段,不需要按照别人博客的修改成自己的,这里用的5900端口,也可以自己换成其他的。</p> +<h1 id="4启动vnc服务">4.启动vnc服务 +</h1><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/12b8d37ebfbb4160a7d50196cf3bd2b7.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +启动了VNC和X11服务,端口号为5902,我这里用的5902,5900和5901被我分给其他的了</p> +<h1 id="5设置自启动">5.设置自启动 +</h1><p>我直接添加开机启动项没有成功,又写了一个脚本,将脚本添加到开机启动项才成功了。</p> +<h2 id="1首先编写一个脚本">(1)首先编写一个脚本 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gedit x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>添加以下内容<br> +第一行是要添加的解释器,后面是要执行的指令内容</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nb">source</span> /etc/init/x11vnc.conf +</span></span></code></pre></td></tr></table> +</div> +</div><p>防止误删,从home移动到/etc/init.d/文件夹中<br> +并添加权限</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mv x11vnc.sh /etc/init.d/ +</span></span><span class="line"><span class="cl">sudo chmod <span class="m">777</span> /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2添加启动项">(2)添加启动项 +</h2><p>点开ubuntu的显示所有应用程序,左下角9个点,找到启动应用程序打开,图中第二行第5个。<br> +<img src="https://img-blog.csdnimg.cn/b1f7234307b64d9ca6844704a100a243.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +点击右侧添加,添加自动启动项。<br> +<img src="https://img-blog.csdnimg.cn/fd2f7303980f4e7598e7f4ce6950ef20.png" +loading="lazy" +alt="在这里插入图片描述" +><br> +添加内容如下;重要的是第二行,</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bash /etc/init.d/x11vnc.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>用bash启动才能成功,保存之后重启,确实可以开机自启了。<br> +<img src="https://img-blog.csdnimg.cn/caa1005977844d8baffbba60e7d6ea93.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="6x11vnc配置安装虚拟显卡驱动">6.x11vnc配置(安装虚拟显卡驱动) +</h1><p>如果你没有实时使用显示器而又想通过vnc远程查看桌面的话,可以考虑安装虚拟显卡驱动,唯一的缺点就是配置好后显示器那边可能无法正常显示</p> +<h2 id="1首先还是安装命令">(1)首先还是安装命令 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install xserver-xorg-video-dummy +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2接下来就是创建配置文件-etcx11xorgconf">(2)接下来就是创建配置文件 <code>/etc/X11/xorg.conf</code> +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Section &#34;Device&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> Driver &#34;dummy&#34; +</span></span><span class="line"><span class="cl"> VideoRam 64000 +</span></span><span class="line"><span class="cl"> Option &#34;IgnoreEDID&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl"> Option &#34;NoDDC&#34; &#34;true&#34; +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> HorizSync 15.0-100.0 +</span></span><span class="line"><span class="cl"> VertRefresh 15.0-200.0 +</span></span><span class="line"><span class="cl">EndSection +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">Section &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Identifier &#34;Screen&#34; +</span></span><span class="line"><span class="cl"> Monitor &#34;Monitor&#34; +</span></span><span class="line"><span class="cl"> Device &#34;Dummy&#34; +</span></span><span class="line"><span class="cl"> DefaultDepth 24 +</span></span><span class="line"><span class="cl"> SubSection &#34;Display&#34; +</span></span><span class="line"><span class="cl"> Depth 24 +</span></span><span class="line"><span class="cl"> Modes &#34;1280x720&#34; +</span></span><span class="line"><span class="cl"> EndSubSection +</span></span><span class="line"><span class="cl">EndSection +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3再修改个文件加点配置">(3)再修改个文件加点配置 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vi /boot/firmware/usercfg.txt +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">framebuffer_width=1280 +</span></span><span class="line"><span class="cl">framebuffer_height=720 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>如果想要恢复显示器的连接,可以先使用ssh访问终端并将<code>/etc/X11/xorg.conf</code>这个文件删除,再次重启即可</strong></p>多线程技术学习(基于Linux)https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post 多线程技术学习(基于Linux)" /><h2 id="1linux多线程概念">1.Linux多线程概念 +</h2><blockquote> +<p><strong>(1)线程:指运行中的程序的调度单位。</strong></p> +</blockquote> +<blockquote> +<p><strong>(2)多线程的优点:</strong></p> +</blockquote> +<ul> +<li>运行与一个线程中的多个线程,他们彼此之间使用<strong>相同的地址空间</strong>,<strong>共享大部分数据</strong>,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。</li> +<li>进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式</li> +<li>应用程序响应速度提高</li> +<li>使多CPU系统更加高效</li> +<li>改善程序结构</li> +</ul> +<blockquote> +<p><strong>(3)线程的生命周期</strong></p> +</blockquote> +<p>就绪-&gt;运行-&gt;阻塞-&gt;终止</p> +<hr> +<h2 id="2linux线程实现">2.linux线程实现 +</h2><blockquote> +<p><strong>(1)线程创建</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含 +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) +</code></pre> +</li> +<li> +<p>函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数 <br> +arg: start_rtn的参数</p> +</li> +</ul> +<blockquote> +<p><strong>(2)线程退出</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +void pthread_exit(void * rval_ptr)</li> +<li>功能:终止调用线程Rval_ptr:线程退出返回值的指针。</li> +</ul> +<blockquote> +<p><strong>(3)线程等待</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_join(pthread_t tid,void **rval_ptr) +</code></pre> +</li> +<li> +<p>功能:阻塞调用线程,直到指定的线程终止。</p> +</li> +<li> +<p>函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针</p> +</li> +</ul> +<blockquote> +<p><strong>(4)线程标识获取</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +pthread_t pthread_self(void)</li> +<li>功能:获取调用线程的 thread identifier</li> +</ul> +<blockquote> +<p><strong>(5)线程清除</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> void pthread_cleanup_push(void (*rtn)(void *),void *arg) +</code></pre> +</li> +<li> +<p>功能:将清除函数压入清除栈</p> +</li> +<li> +<p>函数说明: +Rtn:清除函数 +Arg:清除函数的参数</p> +</li> +</ul> +<hr> +<h2 id="3线程同步的方法">3.线程同步的方法 +</h2><p>进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:</p> +<blockquote> +<p>互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions</p> +</blockquote> +<hr> +<h2 id="4线程的互斥">4.线程的互斥 +</h2><p>线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。</p> +<blockquote> +<p><strong>(1)创建</strong></p> +</blockquote> +<p>在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:</p> +<ul> +<li>对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER</li> +<li>对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。</li> +</ul> +<blockquote> +<p>函数使用: +头文件: +#include &lt;pthread.h&gt;</p> +</blockquote> +<pre><code>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) +int pthread_mutex_destroy(pthread_mutex_t *mutex) +</code></pre> +<blockquote> +<p><strong>(2)加锁</strong></p> +</blockquote> +<p>对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。</p> +<blockquote> +<p>函数使用:</p> +</blockquote> +<pre><code>int pthread_mutex_lock(pthread_mutex_t *mutex) +int pthread_mutex_trylock(pthread_mutex_t *mutex) +</code></pre> +<p>返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。</p> +<blockquote> +<p><strong>(3)解锁</strong></p> +</blockquote> +<p>在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。</p> +<pre><code>int pthread_mutex_unlock(pthread_mutex_t *mutex) +</code></pre> +<hr> +<h2 id="5互斥pk信号量">5.互斥PK信号量 +</h2><blockquote> +<p>Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:</p> +<ol> +<li>mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放</li> +<li>初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。</li> +</ol> +</blockquote> +<hr> +<h2 id="6信号量操作代码演示">6.信号量操作(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;semaphore.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">sem_t sem; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sem_wait(&amp;sem); // 接收信号量 +</span></span><span class="line"><span class="cl"> /* +</span></span><span class="line"><span class="cl"> Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 +</span></span><span class="line"><span class="cl"> 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> //while(strncmp(buf,&#34;end&#34;,3) != 0) +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> sem_init(&amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(scanf(&#34;%s&#34;,buf)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> sem_post(&amp;sem); //增加(解锁)sem指向的信号量 +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="7互斥操作函数演示">7.互斥操作(函数演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">pthread_mutex_t mutex; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sleep(1); +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 互斥加锁 +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 解锁 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_mutex_init(&amp;mutex,NULL); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 对互斥对象加锁锁定 +</span></span><span class="line"><span class="cl"> scanf(&#34;%s&#34;,buf); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 输入后解锁 +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> pthread_mutex_destroy(&amp;mutex); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="8条件变量代码演示">8.条件变量(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1">#include&lt;stdio.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;string.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;pthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;stdlib.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">子线程处理</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_cond_t</span> <span class="n">cond</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">flag</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="o">*</span><span class="k">func</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">flag</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span><span class="o">//</span> <span class="err">互斥加锁</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span><span class="o">//</span> <span class="err">线程同步等待</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> <span class="o">//</span> <span class="err">解锁</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_exit</span><span class="p">(</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_t</span> <span class="n">th</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="err">初始化条件变量</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">,</span><span class="k">func</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_create</span><span class="p">()</span><span class="err">函数在调用进程中启动一个新线程</span><span class="p">,</span><span class="err">创建成功返回</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_create error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;please input string,end with Enter.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">scanf</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">发送信号</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="s2">&#34;end&#34;</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;process end</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char .</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;wait reclaim child thread.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">函数等待由</span><span class="n">thread指定的线程结束</span><span class="err">。如果该线程已经终止,则</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">立即返回。</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_join error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;reclaim child thread successfully.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">条件变量销毁</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git a/tags/linux/page/1/index.html b/tags/linux/page/1/index.html new file mode 100644 index 000000000..d71b2659d --- /dev/null +++ b/tags/linux/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/linux/ + \ No newline at end of file diff --git a/tags/linux/page/2/index.html b/tags/linux/page/2/index.html new file mode 100644 index 000000000..bab78c8fe --- /dev/null +++ b/tags/linux/page/2/index.html @@ -0,0 +1,57 @@ +Tag: Linux - Pager 2 - kurisaW +

Tags

13 pages

Linux

\ No newline at end of file diff --git a/tags/linux/page/3/index.html b/tags/linux/page/3/index.html new file mode 100644 index 000000000..aa06fab5e --- /dev/null +++ b/tags/linux/page/3/index.html @@ -0,0 +1,57 @@ +Tag: Linux - Pager 3 - kurisaW +

Tags

13 pages

Linux

\ No newline at end of file diff --git a/tags/lpc/index.html b/tags/lpc/index.html new file mode 100644 index 000000000..e0e8029b2 --- /dev/null +++ b/tags/lpc/index.html @@ -0,0 +1,55 @@ +Tag: LPC - kurisaW +

Tags

4 pages

LPC

\ No newline at end of file diff --git a/tags/lpc/index.xml b/tags/lpc/index.xml new file mode 100644 index 000000000..7df8dfcfc --- /dev/null +++ b/tags/lpc/index.xml @@ -0,0 +1,2127 @@ +LPC on kurisaWhttps://kurisaw.github.io/tags/lpc/Recent content in LPC on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> \ No newline at end of file diff --git a/tags/lpc/page/1/index.html b/tags/lpc/page/1/index.html new file mode 100644 index 000000000..188572719 --- /dev/null +++ b/tags/lpc/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/lpc/ + \ No newline at end of file diff --git a/tags/lpc55s69/index.html b/tags/lpc55s69/index.html new file mode 100644 index 000000000..71931ec58 --- /dev/null +++ b/tags/lpc55s69/index.html @@ -0,0 +1,55 @@ +Tag: LPC55s69 - kurisaW +

Tags

4 pages

LPC55s69

\ No newline at end of file diff --git a/tags/lpc55s69/index.xml b/tags/lpc55s69/index.xml new file mode 100644 index 000000000..7e323123b --- /dev/null +++ b/tags/lpc55s69/index.xml @@ -0,0 +1,2127 @@ +LPC55s69 on kurisaWhttps://kurisaw.github.io/tags/lpc55s69/Recent content in LPC55s69 on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> \ No newline at end of file diff --git a/tags/lpc55s69/page/1/index.html b/tags/lpc55s69/page/1/index.html new file mode 100644 index 000000000..8dcfdcf6f --- /dev/null +++ b/tags/lpc55s69/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/lpc55s69/ + \ No newline at end of file diff --git a/tags/matter/index.html b/tags/matter/index.html new file mode 100644 index 000000000..d9e848206 --- /dev/null +++ b/tags/matter/index.html @@ -0,0 +1,56 @@ +Tag: Matter - kurisaW +

Tags

8 pages

Matter

\ No newline at end of file diff --git a/tags/matter/index.xml b/tags/matter/index.xml new file mode 100644 index 000000000..74edc917a --- /dev/null +++ b/tags/matter/index.xml @@ -0,0 +1,3547 @@ +Matter on kurisaWhttps://kurisaw.github.io/tags/matter/Recent content in Matter on kurisaWHugo -- gohugo.ioenSun, 20 Aug 2023 00:00:00 +0000【Matter】CHIP设备层设计笔记https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/<img src="https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover.jpg" alt="Featured image of post 【Matter】CHIP设备层设计笔记" /><h1 id="chip设备层设计笔记">CHIP设备层设计笔记 +</h1><p>本文档包含与 CHIP 设备层 ( <code>src/platform</code>) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。</p> +<p>这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。</p> +<p>本文档包含以下部分:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Device-Layer-Adaptation-Patterns" target="_blank" rel="noopener" +>设备层适配模式</a></li> +</ul> +<hr> +<h3 id="设备层适配模式">设备层适配模式 +</h3><p>设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。</p> +<p>CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。</p> +<p>作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。</p> +<p>为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。</p> +<p>尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。</p> +<p>以下各节描述了用于实现这些目标的一些模式。</p> +<ol> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Interface-and-Implementation-Classes" target="_blank" rel="noopener" +>接口和实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Method-Forwarding" target="_blank" rel="noopener" +>方法转发</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Target-Platform-Selection" target="_blank" rel="noopener" +>目标平台选择</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Generic-Implementation-Classes" target="_blank" rel="noopener" +>通用实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Overriding-Generic-Behaviors" target="_blank" rel="noopener" +>覆盖通用行为</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Multiple-Inheritance-and-Subclassing-of-Generic-Implementations" target="_blank" rel="noopener" +>通用实现的多重继承和子类化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Static-Virtualization-of-Generic-Implementation-Behavior" target="_blank" rel="noopener" +>通用实现行为的静态虚拟化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#-ipp-files-and-explicit-template-instantiation" target="_blank" rel="noopener" +>.cpp 文件和显式模板实例化</a></li> +</ol> +<hr> +<h3 id="接口和实现类">接口和实现类 +</h3><p>CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。</p> +<p>外部可见的<em><strong>抽象接口类</strong></em>定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。</p> +<p>实现<em><strong>类</strong></em>提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。</p> +<p>设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。</p> +<p>抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀<code>Impl</code>。在所有情况下,实现类都需要从其接口类公开继承。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for a specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="方法转发">方法转发 +</h3><p>接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。<code>this</code>这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪的重复模板模式</a> ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,<code>ImplClass</code>使转发方法定义更加简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* forward method call... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>作为转发方法目标的实现类上的方法称为*<strong>实现方法*</strong>。每一种转发方法都必须有相应的实现方法。</p> +<p>前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。</p> +<p>实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Let the forwarding methods on ConfigurationManager call implementation +</span></span><span class="line"><span class="cl"> methods on this class. */ +</span></span><span class="line"><span class="cl"> friend ConfigurationManager; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">private: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR _Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding implementation method... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding static implementation method... */ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="目标平台选择">目标平台选择 +</h3><p>实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of ConfigurationManager.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#define CONFIGURATIONMANAGERIMPL_HEADER \ +</span></span><span class="line"><span class="cl"> &lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h&gt; +</span></span><span class="line"><span class="cl">#include CONFIGURATIONMANAGERIMPL_HEADER +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span></code></pre></td></tr></table> +</div> +</div><p>该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。</p> +<p>每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如<code>ESP32</code>)。所有此类文件都具有相同的文件名(例如<code>ConfigurationManagerImpl.h</code>),并且每个文件都包含类似名称的类的定义(<code>ConfigurationManagerImpl</code>)。</p> +<p>特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 <code>src/adaptations/device-layer/ESP32</code>)。与特定于平台的头目录一样,这些子目录以目标平台命名。</p> +<p>设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 <code>--device-layer=&lt;target-platform&gt;</code>。传递 &ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET ESP32 +</span></span><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET_ESP32 1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>&ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。</p> +<h3 id="通用实现类">通用实现类 +</h3><p>通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。</p> +<p>为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。</p> +<p>通用实现基类被实现为遵循 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪重复模板模式的</a>C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Implementation provided by +</span></span><span class="line"><span class="cl"> generic base class. */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); /* &lt;-- Invoked when GetDeviceId() called. */ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="覆盖通用行为">覆盖通用行为 +</h3><p>如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。</p> +<p>新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using GenericImpl = GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Call the generic implementation to get the device id. */ +</span></span><span class="line"><span class="cl"> uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Special case the situation where the device id is not known. */ +</span></span><span class="line"><span class="cl"> if (deviceId == kNodeIdNotSpecified) { +</span></span><span class="line"><span class="cl"> deviceId = PLATFORM_DEFAULT_DEVICE_ID; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return deviceId; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现的多重继承和子类化">通用实现的多重继承和子类化 +</h3><p>具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericWiFiConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;, /* &lt;-- WiFi features */ +</span></span><span class="line"><span class="cl"> public GenericThreadConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Thread features */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on all platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on FreeRTOS platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl_FreeRTOS +</span></span><span class="line"><span class="cl"> : public GenericPlatformManagerImpl&lt;ImplClass&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现行为的静态虚拟化">通用实现行为的静态虚拟化 +</h3><p>在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。</p> +<p>例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过<code>GetDeviceId()</code>从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。</p> +<p><code>this</code>遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数<code>Impl()</code>有助于使代码简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericConfigurationManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ConfigurationManagerImpl</span> <span class="n">final</span> +</span></span><span class="line"><span class="cl"> <span class="p">:</span> <span class="n">public</span> <span class="n">ConfigurationManager</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">public</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">friend</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">delegate</span> <span class="n">to</span> <span class="n">the</span> <span class="n">implementation</span> <span class="k">class</span> <span class="n">to</span> <span class="n">read</span> <span class="n">the</span> <span class="s1">&#39;device-id&#39;</span> <span class="n">config</span> <span class="n">value</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="err">“</span><span class="n">device</span><span class="o">-</span><span class="n">id</span><span class="err">”</span><span class="p">,</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">ConfigurationManagerImpl</span><span class="p">::</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">read</span> <span class="n">value</span> <span class="n">from</span> <span class="n">platform</span><span class="o">-</span><span class="n">specific</span> <span class="n">key</span><span class="o">-</span><span class="n">value</span> <span class="n">store</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。</p> +<p>同样,委托是通过转换<code>this</code>指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericPlatformManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">Delegate</span> <span class="n">work</span> <span class="n">to</span> <span class="n">method</span> <span class="n">that</span> <span class="n">can</span> <span class="n">be</span> <span class="n">overridden</span> <span class="n">by</span> <span class="n">implementation</span> <span class="k">class</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">provide</span> <span class="n">default</span> <span class="n">implementation</span> <span class="n">of</span> <span class="n">DispatchEventToApplication</span><span class="p">()</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="cpp-文件和显式模板实例化">.cpp 文件和显式模板实例化 +</h3><p>C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。</p> +<p>为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀<code>.cpp</code>。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.cpp */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">CHIP_ERROR GenericConfigurationManagerImpl&lt;ImplClass&gt;::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。<a class="link" href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation" target="_blank" rel="noopener" +>为了避免这种情况,设备层使用显式模板实例化</a>的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件<code>extern template class</code>在使用模板类之前都包含一个声明。这告诉编译器<em>不要</em>在该上下文中实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.h */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Instruct the compiler to instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span></span><span class="line"><span class="cl"><span class="c1">// class only when explicitly asked to do so. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">extern</span> <span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并<code>template class</code>使用定义来强制显式实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.cpp */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Fully instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; class. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。</p>【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/Mon, 19 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/matter%E5%A6%82%E4%BD%95%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8B%E6%B5%8B%E8%AF%95matter%E5%BA%94%E7%94%A8%E7%BA%A7%E9%80%9A%E4%BF%A1%E8%99%9A%E6%8B%9F%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)" /><h1 id="如何在linux平台下测试matter应用级通信虚拟设备">如何在Linux平台下测试Matter应用级通信(虚拟设备) +</h1><hr> +<h2 id="准备工作">准备工作 +</h2><h3 id="1-递归克隆matter仓库">1. 递归克隆Matter仓库 +</h3><p>执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果克隆过程中发生报错,请执行如下命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于我们的环境构建配置均是基于Matter1.0,所以我们需要切换到v1.0分支下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout v1.0 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2-matter依赖项安装">2. Matter依赖项安装 +</h3><p>Matter 构建依赖于以下软件包及环境库:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果通过<code> build_examples.py</code> 和 <code>-with-ui</code> 变体进行构建,也要安装 SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-matter环境构建">3. Matter环境构建 +</h3><p>执行<code>scripts/activate.sh</code>脚本。该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190833624.png" +loading="lazy" +alt="image-20230619083303148" +></p> +<p>如果显示环境已过期可执行如下命令进行更新(一般如果没提示环境已过期的提示不建议执行这一步,编译会花一段时间):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-安装zap">4. 安装zap +</h3><blockquote> +<p>注意:zap 包目前不可用<code>arm64</code>(比如在 Raspberry PI 上编译时)。</p> +</blockquote> +<ul> +<li>**Step1:ZAP需要Node.js来运行,请先确保你的计算机上已经安装了Node.js。**可以使用以下命令:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node -v +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果安装的话不出意外会出现版本号。</p> +<ul> +<li><strong>Step2:zap安装</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> connectedhomeip/scripts/tools/zap +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">python3 zap_download.py +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是安装日志:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">root@kurisaw-virtual-machine:/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/scripts/tools/zap# python3 zap_download.py +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Found required zap version to be: v2023.04.27-nightly +</span></span><span class="line"><span class="cl">2023-06-19 13:28:22 root INFO Fetching: https://github.com/project-chip/zap/releases/download/v2023.04.27-nightly/zap-linux.zip +</span></span><span class="line"><span class="cl">2023-06-19 13:29:20 root INFO Data downloaded, extracting ... +</span></span><span class="line"><span class="cl">2023-06-19 13:29:25 root INFO Done extracting. +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_INSTALL_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step3:配置zap环境变量</strong></li> +</ul> +<p>我们看上面 zap 安装日志,其中最后导出了zap 的安装路径为<code>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly</code>,在此目录下有个 zap 脚本,我们这个位置一定要记住!!</p> +<p>设置<code>ZAP_DEVELOPMENT_PATH</code>环境变量(这里的路径需要根据上面安装zap后提示的路径进行设置,不能一昧照抄)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><strong>Step4:运行zap引导程序</strong></li> +</ul> +<p>执行如下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./run_zaptool.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>效果如下:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191346155.png" +loading="lazy" +alt="image-20230619134658521" +></p> +<ul> +<li><strong>Step4:为了方便我们后续使用zap,我们设置root终端下自启动:</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">vi ~/.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>在<code>.bashrc</code>文件最末添加如下代码,也就是配置zap环境变量</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter/connectedhomeip/connectedhomeip/.zap/zap-v2023.04.27-nightly +</span></span></code></pre></td></tr></table> +</div> +</div><p>保存退出!</p> +<h2 id="应用程序构建">应用程序构建 +</h2><p>在官方文档中提供有两种构建方式:</p> +<ul> +<li>通过脚本构建</li> +<li>使用 Gn 和 Ninja 命令构建</li> +</ul> +<h3 id="1-通过脚本构建">1. 通过脚本构建 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build_script.sh EXAMPLE_DIR OUTPUT_DIR <span class="o">[</span>ARGUMENTS<span class="o">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>build_script.sh</code> 是脚本的文件名;</li> +<li><code>EXAMPLE_DIR</code> 是示例项目的目录路径;</li> +<li><code>OUTPUT_DIR</code> 是构建输出的目录路径;</li> +<li><code>[ARGUMENTS]</code> 是可选的其他参数,用于设置gn和ninja命令的选项。</li> +</ul> +<h4 id="11-构建示例">1.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./scripts/examples/gn_build_example.sh examples/placeholder/linux out/debug/simulated/ <span class="nv">chip_tests_zap_config</span><span class="o">=</span><span class="se">\&#34;</span>app1<span class="se">\&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190835972.png" +loading="lazy" +alt="image-20230619083551820" +></p> +<h4 id="12-运行构建">1.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./out/simulated/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306190843752.png" +loading="lazy" +alt="image-20230619084309631" +></p> +<h3 id="2-通过-gn-和-ninja-构建应用程序">2. 通过 gn 和 ninja 构建应用程序 +</h3><h4 id="21-构建示例">2.1 构建示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span><span class="line"><span class="cl">gn gen --check --root<span class="o">=</span>examples/placeholder/linux out/simulated --args<span class="o">=</span><span class="s2">&#34;chip_tests_zap_config=\&#34;app1\&#34;&#34;</span> +</span></span><span class="line"><span class="cl">ninja -C out/simulated +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22-运行构建">2.2 运行构建 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./out/app1/chip-app1 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191510937.png" +loading="lazy" +alt="image-20230619151054483" +></p> +<h2 id="测试应用程序">测试应用程序 +</h2><p>在前面的应用程序构建那一节中我们已经完成了应用程序的构建并且成功运行了构建,同时我们在日志中也可以看到生成了QR码的链接,我们将其复制到浏览器打开即可得到二维码</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191513515.png" +loading="lazy" +alt="image-20230619151353417" +></p> +<p>我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> out/debug +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./chip-tool onoff on 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff off 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> accepted-command-list 0x654321 <span class="m">1</span> +</span></span><span class="line"><span class="cl">./chip-tool onoff <span class="nb">read</span> on-time 0x654321 <span class="m">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306191530858.png" +loading="lazy" +alt="image-20230619153015727" +></p> +<p>具体更多的使用命令可参考:<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md" target="_blank" rel="noopener" +>Chip tool</a></p> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/simulated_device_linux.md" target="_blank" rel="noopener" +>simulated_device_linux</a></li> +<li><a class="link" href="https://github.com/project-chip/zap" target="_blank" rel="noopener" +>zap</a></li> +</ul>【Matter】Matter学习笔记1https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/Wed, 14 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/<img src="https://kurisaw.github.io/p/mattermatter%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01/cover.jpg" alt="Featured image of post 【Matter】Matter学习笔记1" /><h1 id="matter学习笔记1">Matter学习笔记1 +</h1><hr> +<p>在了解Matter之前,可以选择先了解以下前提知识:</p> +<ul> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118389957" target="_blank" rel="noopener" +>matter网络基础之—Thread</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/118553988" target="_blank" rel="noopener" +>matter网络基础之—Wi-Fi</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/119253287" target="_blank" rel="noopener" +>边界路由器,网关和Wi-Fi接入点</a></li> +<li><a class="link" href="https://blog.csdn.net/qq_42860989/article/details/120067170" target="_blank" rel="noopener" +>Thread地址(IPv6 and RLOC16)</a></li> +</ul> +<blockquote> +<p>以上资料来自CSDN博主:<a class="link" href="https://blog.csdn.net/qq_42860989" target="_blank" rel="noopener" +>Eagle115</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>近日,CSA联盟(Connectivity Standards Alliance)正式对外发布了Matter 1.0 标准,并宣布认证计划现已开放。这意味着智能家居品牌可以对其产品进行相关测试和认证,一旦获得认证,公司就可以开始销售带有Matter 标志的设备。</p> +<p>Matter 最初的项目名称是Project Chip(CHIP),目前由 CSA联盟维护。它是一个<strong>统一标准的物联网通信协议,旨在将繁杂的智能家居设备收归到统一的通信标准</strong>。</p> +<p>Matter 作为一个<strong>应用级的协议</strong>,向下屏蔽了<strong>设备制造商的生态和系统,让各种智能家居设备之间能相互通信</strong>。例如,一个 Matter 认证的智能灯泡可以由另一个厂家生产的同样经过认证的设备来控制。Matter 是基于ip的协议,支持wifi、 Thread、 Internet三种不同的底层协议栈。</p> +<p>Matter 采用不同的通讯协议和技术为未来智能家居行业提供了不同场景下的解决方案:</p> +<ul> +<li><strong>低功耗蓝牙技术</strong>:低功耗蓝牙作为一种专门设计用于低功耗设备之间通信的无线通信技术,它可以在较低的功率下实现较长的通信距离,因此非常适合用于智能家居设备之间的连接。Matter 使用低功耗蓝牙技术进行设备之间的连接和控制。</li> +<li><strong>二维码进行配置</strong>:二维码是一种快速扫描的图形码,可以用于快速识别设备身份和配置设备。在 Matter 中,用户可以扫描设备上的二维码,以快速将设备添加到智能家居网络中,而无需手动输入复杂的网络配置信息。</li> +<li><strong>Wi-Fi 技术进行高速数据传输</strong>:Wi-Fi 技术是一种通信技术,可以提供高速的无线网络连接,因此非常适合用于传输大量数据,例如高清视频和音频数据。在 Matter 中,设备可以通过 Wi-Fi 进行高速数据传输,以实现高质量的音视频体验。</li> +<li><strong>Thread 协议进行低速数据传输</strong>:Thread 协议是一种低功耗、安全、可靠的无线通信协议,它适用于智能家居设备之间的低速数据传输。在 Matter 中,设备可以使用 Thread 协议进行低速数据传输,例如传输传感器数据、控制指令等。</li> +</ul> +<h2 id="matter协议架构">Matter协议架构 +</h2><h3 id="1matter-over-ipv6">1.Matter Over IPV6 +</h3><p>该标准建立在一个共同的信念之上,即智能家居设备应该安全、可靠且无缝使用。通过建立在互联网协议 (IP) 之上,Matter 支持智能家居设备、移动应用程序和云服务之间的通信,并为设备认证定义了一组特定的基于 IP 的网络技术。</p> +<p>IPv6(Internet Protocol version 6)是互联网协议的一种,它是 IPv4 协议的后继者,当然并不是说这是一种全新的技术,更多的可以看作是IPV4 协议的扩展。IPv6 提供了更大的地址空间(128位)、更好的安全性(引入IPsec协议作为默认选项)、更高的性能和更多的扩展性,是未来互联网发展的重要基础。</p> +<p>下面是IPV4 和 IPV6 的一些区别:</p> +<table> +<thead> +<tr> +<th style="text-align:center">区别</th> +<th style="text-align:center">IPV4</th> +<th style="text-align:center">IPV6</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">地址长度</td> +<td style="text-align:center">32 bits</td> +<td style="text-align:center">128 bits</td> +</tr> +<tr> +<td style="text-align:center">地址数量</td> +<td style="text-align:center">约<strong>4x10^9</strong></td> +<td style="text-align:center">约<strong>3.4×10^38</strong></td> +</tr> +<tr> +<td style="text-align:center">地址类型</td> +<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> +<td style="text-align:center">通过 DHCPv6 动态分配</td> +</tr> +<tr> +<td style="text-align:center">安全性</td> +<td style="text-align:center">IPsec(Internet协议安全标准) 为可选项</td> +<td style="text-align:center">IPsec 为默认选项</td> +</tr> +<tr> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +<td style="text-align:center">&mdash;</td> +</tr> +</tbody> +</table> +<h3 id="2matter协议架构">2.Matter协议架构 +</h3><p>Matter 旨在为智能家居设备构建一个通用的基于 IPv6 的通信协议。该协议定义了将部署在设备上的应用层和不同的链路层,以帮助维护互操作性。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121952614.png" +loading="lazy" +></p> +<p>为了解决网络通信壁垒,Matter网络层本身基于 IPV6,因此<strong>天生具备IP连接能力</strong>,可以与WIFI、Thread、以太网等通讯协议配合使用,而蓝牙则仅在配网过程使用;</p> +<p>Matter 还支持<strong>桥接</strong>等其他智能家居技术(例如 Zigbee、Bluetooth Mesh 和 Z-Wave)。这也就意味着,基于这些协议的设备可以像使用 Matter 设备一样运行<strong>Bridge</strong>;</p> +<p>由于Matter是基于应用层的协议,也就是说在未来即便有新的网络层协议的出现,Matter也可以很方便的兼容和支持到新协议,从长远发展来看具有很好的前瞻性!</p> +<h3 id="3matter标准协议架构">3.Matter标准协议架构 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121138795.png" +loading="lazy" +></p> +<p><strong>Matter标准协议架构总体流程分析:</strong></p> +<p>首先使用Interaction Model构建一个Action;在Action Framing这一层中,该Action会被序列化为一份指定的压缩二进制格式,表示可以在设备上执行设备交互的一组操作;处理后的Action帧通过Security层进行加密和签名处理,确保通信双方信息传输的机密性和可靠性;当Action经过序列化、加密和签名后,Message Layer会指定一份必选及可选的头字段构造Payload格式,其中头字段中包含了规定消息的属性及一些逻辑路由信息;当payload被 Message Layer 层构造后, 会使用基于IP的数据传输协议 (TCP协议或Matter的消息可靠协议<a class="link" href="" >Message Reliability Protocol</a>);一旦对方设备收到数据后,数据流则沿着协议栈向上移动,即各个层反转发送方对数据执行的操作,最终将消息传递给应用程序。</p> +<p>后面我们会重点讲解设备数据模型(Data Model)和互动模型(Interaction Model),这两部分是Matter互联互通的前提!</p> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p>原理上,任何支持IPV6协议的网络都可以部署Matter,我们重点关注三种链路层技术:以太网(Ethernet)、WIFI和 Thread。</p> +<p>在 Matter 协议中,Matter将网络视为共享资源,它不规定独占网络的所有权或访问权。因此我们可以在同一组成IP的网络下覆盖多个Matter网络。</p> +<p>Matter协议还可以在没有公网IPv6基础设施的情况下运行,经资料查询得知,主要是因为<strong>Matter协议也支持Thread网络协议,其底层是基于IEEE 802.15.4的,并使用了6LoWPAN作为IPv6的适配层</strong>。而 <strong>6LoWPAN协议</strong> 提供了一种在低功耗无线传感器网络中使用IPv6的方法,它可以将IPv6数据包压缩到非常小的尺寸,从而使得这些数据包可以在不需要较大的IP地址空间的情况下传输。这使得Matter设备可以使用私有IPv6地址而不需要公共IPv6地址,因此不需要依赖公网IPv6基础设施。</p> +<p>因此,Matter协议不需要依赖公网IPv6基础设施,也不需要依赖互联网服务提供商的支持,可以在与公网断开连接或有防火墙的网络中操作,这使得它可以在更广泛的场景下进行部署和使用。</p> +<h3 id="mesh组网">Mesh组网 +</h3><p>在了解Matter网络拓扑结构之前,我们可以先来了解下 Mesh 组网。</p> +<p>目前最流行的全屋WiFi方案主要有两种:<strong>Mesh路由器组网</strong>和<strong>AC+AP</strong>两种方案。而Mesh路由器组网由于其实惠的价格和较为稳定的链路连接性能以及安装的简便性,目前在全屋智能网络的选择还是比较热门的。</p> +<p>无线Mesh网络是一种新无线局域网类型,与传统WLAN不同的是,<strong>无线Mesh网络</strong>中的<strong>AP</strong>可以采用<strong>无线连接</strong>的方式进行互连,并且<strong>AP间可以建立多跳的无线链路</strong>。简单来说,就是当WIFI覆盖不了的时候,在有WIFI信号的时候放置一个路由器,可以作为Mesh路由的中继节点,透过这个节点,将WIFI信号覆盖到所有需要覆盖的地方;是一个动态的可以不断扩展的网络架构,任意的WIFI节点设备均可以保持无线互联。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +loading="lazy" +alt="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306132314987.png" +></p> +<p>这个很直观的体现就是大学里每层走廊中间都会架设一台路由,而你每移动一个楼层,你手机的校园网都会重新连接,也就是手机信号会快速自动重连距离你最近的一台路由,这就构成了一个庞大的无线链路网络。下面我们再来了解下Matter 的网络拓扑结构主要分为单一网络拓扑和星形网络拓扑:</p> +<h3 id="1单一网络拓扑">1.单一网络拓扑 +</h3><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121601076.png" +loading="lazy" +></p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121516744.png" +loading="lazy" +></p> +<p>在单一网络拓扑中,所有的 Matter 设备都连接到一个单一的逻辑网络。 它可以是<strong>Thread/802.15.4网络</strong>、<strong>Wi-Fi网络</strong>或<strong>以太网网络</strong>。在 Wi-Fi/以太网的情况下,网络实际上可以跨越多个Wi-Fi和/或以太网段,<strong>前提是所有段都在链路层桥接</strong>。 节点(Node)是Fabric中的 Matter设备的单个实例,可在IP网络上运行。</p> +<p>在单一网络拓扑中的每个节点都通过单个网络接口与Fabric中的每个其他节点进行通信。</p> +<p>在Matter 中,分属不同网络的设备可以进行同端通信,这也就意味着一个WIFI设备可以和一个Thread进行相互的信息转发,而Matter则扮演了一个虚拟网络的身份,并称其为<strong>Fabric</strong>。</p> +<blockquote> +<p>注:Fabric是共享同一个Trusted Root的Matter设备的集合。Matter中Trusted Root作为根CA,颁发NOC证书,识别节点身份。在一个Fabric内,每个节点都有一个唯一标识Node ID。Fabric作为一个命名空间来管理所有权,在Fabric范围内使用标识符确保资源的分配和选择的唯一性。</p> +</blockquote> +<h3 id="2星形网络拓扑">2.星形网络拓扑 +</h3><ul> +<li><strong>AP(Access Point)</strong>:WI-FI无线接入点,AP 负责向 STA 提供 Wi-Fi 信号,并提供连接互联网的网络服务。</li> +<li><strong>STA(Station)</strong>:STA 是 Wi-Fi 中的无线客户端,即 Station。STA 可以是智能手机、平板电脑、笔记本电脑等各种设备,它们可以通过 Wi-Fi 连接到无线接入点,访问互联网或者局域网中的资源。</li> +<li><strong>BR(Border Router)</strong>:指的是边界路由器,BR 是一种网络设备,可以连接两个或多个 IP 子网,并将它们转换为同一个 Thread 网络,使得不同子网中的设备可以互相通信。BR 是 Thread 网络中的核心设备之一,通常由路由器或者网关设备提供。</li> +<li><strong>ED(End device)</strong>:指的是终端设备,ED 是 Thread 网络中的客户端设备,如智能手机、平板电脑、笔记本电脑等。ED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +<li><strong>R(Router)</strong>:指的是内部路由器。R 是一种网络设备,可以连接多个 ED 和其他 R,负责在 Thread 网络中进行路由选择和数据转发。</li> +<li><strong>SED(Sleepy End Device)</strong>:指的是低功耗终端设备。SED 是一种特殊的终端设备,通常采用低功耗的无线技术,可以在不需要进行通信时进入睡眠模式,从而延长电池寿命。SED 可以直接连接到 BR 或者 R,也可以通过其他设备中继进行通信。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306121605090.png" +loading="lazy" +></p> +<p>星形网络拓扑由多个外围网络组成,这些网络通过Hub连接在一起。Hub通常是客户家庭网络(Wi-Fi/以太网)中的设备,而外围网络可以是任何支持的网络类型。<strong>外围网络必须始终通过一个或多个边界路由器(Border Router)直接连接到Hub。</strong></p> +<p>在架构上,任何数量的外围网络可以存在于单个Fabric中,包括相同类型的多个网络。节点可以具有到任何网络(Hub或外围设备)的接口,并且可以直接与同一网络上的其他节点通信。然而,任何必须跨越网络边界才能到达目的地的通信必须通过边界路由器(Border Router)。</p> +<p>该协议对边界路由器提出了一系列要求。这些要求涉及地址分配、路由分配和广播、多播支持和代理发现。</p> +<blockquote> +<p>注:在现Matter1.0版本规范中,Thread是主要支持的LLN(Low-Power and Lossy Network)。在许多情况下,客户安装将尝试维护一简单的网络拓扑,包括一个Wi-Fi/以太网子网和一个单Thread网络。但是,可以支持多个Thread网络。</p> +</blockquote> +<h2 id="设备数据模型date-model">设备数据模型(Date Model) +</h2><p>在 Matter 中的设备具有明确定义的<strong>数据模型</strong> (<strong>DM</strong>),这是对设备功能的分层建模。在此层次结构的顶层,有一个<strong>Device</strong>。</p> +<h3 id="1设备和端点nodeendpoint">1.设备和端点(Node、Endpoint) +</h3><p>所有设备(包括智能手机和家居助理)均由**Node(节点)**组成。“节点”是网络中可以标识为唯一且可寻址的资源,用户可以感知到整个功能。Matter 中的网络通信始于和终止节点。</p> +<p>一组节点包含了多组<strong>Endpoint(端点)</strong>。<strong>而每个端点都封装了一个功能集</strong>。例如,端点1可能涉及照明功能,而端点2可能涉及移动侦测,以及其他与实用程序(例如设备 OTA)的处理方式。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122042737.png" +loading="lazy" +></p> +<h3 id="2节点角色node-roles">2.节点角色(Node roles) +</h3><p>在Matter 中,每一个物理设备都被称之为<strong>Node</strong>,Node 使用**Node ID(64bit)**来进行表示,在Fabric范围内是唯一的!</p> +<p><strong>Node roles</strong>是一组相关的行为。每个节点可能有一个或多个role。Node roles 包括:</p> +<ul> +<li><strong>Commissioner :执行</strong><a class="link" href="https://developers.home.google.com/matter/primer/commissioning" target="_blank" rel="noopener" +>调试</a>的节点 。</li> +<li><strong>控制器</strong>:可以控制一个或多个节点的节点。例子包括Google Home app (GHA), Google Assistant, 和Google Nest Hub (2nd gen). 某些设备类型(例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>开/关灯开关</a>)具有控制器角色。</li> +<li><strong>Controlee</strong> : 可以被一个或多个节点控制的节点。大多数设备类型都可以是 Controlee,除了一些具有 Controller 角色的设备类型,例如<a class="link" href="https://developers.home.google.com/matter/supported-devices#onoff_light_switches" target="_blank" rel="noopener" +>On/Off Light Switch</a>。开/关灯开关只能<em>是</em>控制器。它不能是受控人。</li> +<li><strong>OTA Provider</strong> : 可以提供 OTA 软件更新的节点。</li> +<li><strong>OTA 请求者</strong>:可以请求 OTA 软件更新的节点。</li> +</ul> +<h3 id="3集群cluster">3.集群(Cluster) +</h3><p>在一个<strong>Endpoint</strong>中,一个 Node 有一个或多个<strong>Clusters</strong>。这些是设备层次结构中的另一个步骤,因为它们将特定功能分组,例如 智能插头上的<em>开/关</em>集群,或可调光端点上的<em>电平控制集群。</em></p> +<p>一个节点也可能有多个端点,每个端点都创建一个具有相同功能的实例。例如,灯具可能会暴露对单个灯的独立控制,或者电源板可能会暴露对单个插座的控制。</p> +<h4 id="31-属性attributes">3.1 属性(Attributes) +</h4><p>在最后一层,我们会找到<strong>Attributes</strong>,这是节点持有的状态,表示可以读取或写入的内容,支持多种数据格式,实际中代表了智能设备的相关属性(如门的开关、室内温度等)。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122111729.png" +loading="lazy" +></p> +<h4 id="32-命令commands">3.2 命令(Commands) +</h4><p>除了 Attributes 之外,Clusters 还有<strong>Commands</strong>,也就是<strong>触发 Cluster 进行某种行为的指令</strong>。它们等同于Matter远程过程调用的 DM。命令类似于<em>动词</em>,例如<em>Door Lock</em>集群上的 <em>lock door</em>。命令可能会产生响应和结果;在 Matter,这样的响应也被定义为命令,以相反的方向进行。</p> +<h4 id="33-事件events">3.3 事件(Events) +</h4><p>最后,Clusters 也可能有<strong>Events</strong>,它<strong>可以被认为是过去状态转换的记录</strong>。虽然属性代表<strong>当前状态</strong>,但事件是<strong>过去</strong>的日志,包括单调递增的计数器、时间戳和优先级。它们能够捕获状态转换,以及使用属性不容易实现的数据建模。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122122628.png" +loading="lazy" +></p> +<p><code>Endpoint 0</code>作为<code>Utility Clusters</code><strong>保留。Utility Clusters 是特定的集群,它包含端点上的服务功能,例如发现、寻址、诊断和软件更新</strong>。另一方面,**Application(应用集群)**支持主要操作,例如开/关或温度测量。</p> +<h3 id="4-cluster分类">4. Cluster分类 +</h3><p>cluster可以定义为<strong>工具(Utility) Cluster</strong>或<strong>应用(Application) Cluster</strong>。</p> +<h4 id="41-工具utility-cluster">4.1 工具(Utility) Cluster +</h4><p>工具cluster不是端点的主要应用程序操作的一部分。它可以用于配置、发现、寻址、诊断、监控设备运行状况、软件更新等。它可能与对应的cluster存在临时关系。</p> +<blockquote> +<p>作用域为端点的工具cluster示例:标识符、描述符、绑定、组等。 适用于该节点的工具cluster +示例:基本信息、诊断等。</p> +</blockquote> +<h4 id="42-应用application-cluster">4.2 应用(Application) Cluster +</h4><p>应用cluster支持端点的主要操作。应用cluster可以支持和一个或多个应用程序交互,既包括client也包括server。</p> +<blockquote> +<p>应用cluster示例:</p> +<ul> +<li>On/Off cluster —— client向server发送命令</li> +<li>Temperature Measurement cluster —— server向client报告数据</li> +</ul> +</blockquote> +<p>应用程序cluster不是工具cluster,即使它本身可能支持实用的工具功能,如校准、操作模式等。但应用程序cluster规范不应该涉及其应用领域之外的层级和过程。</p> +<blockquote> +<p>示例:一个特定的温度测量cluster可能存在于不同的设备上,或在不同的网络中,每个设备具有不同的安全与配网机制和/或策略。 +示例:commissioning cluster的范围是配网,而不是测温。</p> +</blockquote> +<h3 id="5-clients-and-servers">5. Clients and Servers +</h3><p>Clusters 可能是<strong>Client Cluster</strong>或<strong>Server Cluster</strong>。服务器是<strong>有状态的</strong>,保存属性、事件和命令;而客户端是 <strong>无状态的</strong>,其职责是启动与远程服务器集群的<strong>交互</strong>,从而执行:</p> +<ul> +<li><strong>读取</strong>和<strong>写入</strong>其远程属性。</li> +<li><strong>读取</strong>其远程事件。</li> +<li><strong>调用</strong>其远程命令。</li> +</ul> +<p>虽然 DM 在节点内是分层的,但节点之间的关系不是。Matter中的节点没有<code>controller/peripheral</code> 或 <code>leader/follower</code>关系。相反,关系是水平的:任何 Cluster 都可以是<strong>Server</strong>或<strong>Client</strong>。因此,<strong>对于不同的集群和功能,节点可能既是服务器又是客户端。</strong></p> +<p>例如,我们可能有两个台灯:<strong>节点 A</strong>和<strong>节点 B</strong>。两个节点都实现了一个<em>开/关灯</em>设备类型。此设备类型包括控制其各自物理光输出的<em>开/关服务器集群。</em></p> +<p>但是,就像典型的台灯一样,我们的物理设备还将包括一个开/关灯 开关设备类型,用于其本地开/关。此设备类型必须实现<em>开/关客户端</em>集群,以便它可以控制服务器集群。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306122240843.png" +loading="lazy" +></p> +<p>在此示例中,节点 A 上的开/关客户端集群正在更改节点 A 和节点 B 上的开/关服务器集群的属性,而节点 B 的客户端集群仅更改节点 B 本身上的服务器集群。</p> +<p>在下一节中,我们将详细介绍客户端和服务器集群如何交互: <strong>Interaction Model(交互模型)</strong>。</p> +<h2 id="交互模型">交互模型 +</h2><h3 id="1概念">1.概念 +</h3><p>如果我们不能对节点执行操作,那么节点的数据模型 (DM) 就不相关了。<strong>交互模型</strong>(<strong>IM</strong>),定义了一个节点的 DM 与其他节点的 DM 的关系:即 IM 作为 DM 之间通信的通用语言。</p> +<p><strong>节点通过以下方式相互交互:</strong></p> +<ul> +<li>读取和订阅属性和事件</li> +<li>写入属性</li> +<li>调用命令</li> +</ul> +<p>每当一个节点与另一个节点建立加密通信序列时,它们就构成了<strong>交互</strong>关系。<strong>Interactions 可能由一个或多个Transactions组成,而 Transactions 由一个或多个Action组成</strong>,可以理解为 Node 之间的 IM 级消息。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306140839728.png" +loading="lazy" +></p> +<p>Matter 支持多个操作,例如从另一个节点请求属性或事件的读取请求操作,或其响应,报告数据操作,它将信息从服务器返回到客户端。</p> +<h4 id="11-发起者initiators-和目标targets">1.1 发起者(Initiators )和目标(Targets) +</h4><p>在Matter中,节点的发起目标被称为<strong>发起者(Initiators )</strong>,而响应的节点则作为<strong>目标(Target)</strong>。一般来说,发起者是客户端集群,而目标是客户端集群。</p> +<h4 id="12-组groups">1.2 组(Groups) +</h4><p>在Matter中节点可能隶属于某个组。设备组作为一种机制,主要用于在统一操作中同时寻址并向多个设备发送消息。在一个 Group 中,所有的节点共享同一个 Group ID(16位整型)。</p> +<p>为了完成组级通信(群播),Matter 利用IPV6 多播消息,并且让所有的组成员都具有相同的多播地址。</p> +<h4 id="13-路径path">1.3 路径(Path) +</h4><p><strong>当我们想要与属性、事件或命令进行交互时,我们需要为这种交互指定 Path ,也就是属性、事件和命令在节点的数据模型层次结构中的位置。</strong></p> +<blockquote> +<p>注:Path 也可以使用<strong>Groups</strong>或者**统配交互符(Wildcard Operators)**同时处理多个节点或集群,从而减少操作的数量。</p> +</blockquote> +<p>Path这种机制对提高通信的响应能力起到很重要的作用。例如:当用户想要关闭所有灯光,语音助手可以与组内多个灯建立单个的交互,而不是传统的一系列单独的交互。</p> +<p>Matter Path 使用规范:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;path&gt; = &lt;node&gt; &lt;endpoint&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span><span class="line"><span class="cl">&lt;path&gt; = &lt;group ID&gt; &lt;cluster&gt; &lt;attribute | event | command&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这些路径构建块中,端点和集群还可能包括用于选择多个节点实例的通配符运算符。</p> +<h4 id="14-定时和非定时timed--untimed">1.4 定时和非定时(Timed &amp; Untimed) +</h4><p>有两种执行写入或调用 Matter 的方式:定时的和非定时的。定时交易为写入/调用动作的发送建立了一个最大的超时。这个超时的目的是为了防止对交易的拦截攻击。它特别适用于对资产进行门禁的设备,如车库开门器和锁。</p> +<h3 id="2-read-transactions">2. Read Transactions +</h3><p>与 Nodes 交互时的第一个用例 Matter是从另一个节点读取的属性,例如来自传感器的温度值。在此类交互中,必须执行的第一个操作是读取请求操作。</p> +<h4 id="21-读取请求操作read-request-action">2.1 读取请求操作(Read Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>在此 Action 中,Initiator 会查询 Target 提供的以下请求:</p> +<ul> +<li><strong>属性请求</strong>:零个或多个目标属性的列表。该列表由零个或多个目标请求属性的路径组成。</li> +<li><strong>事件请求</strong>:目标请求事件的零个或多个路径列表。</li> +</ul> +<p>目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作;当目标接收到读取请求操作后,它将使用请求的信息组装一个报告数据操作。详见下图:</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141108121.png" +loading="lazy" +></p> +<h4 id="22-报告请求数据report-data-action">2.2 报告请求数据(Report Data Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>在此 Action 中,Target 响应:</p> +<ul> +<li><strong>属性报告(Attribute Reports)</strong>:读取操作请求中请求的零个或多个报告属性的列表。</li> +<li><strong>事件报告(Event Reports)</strong>:零个或多个报告事件的列表。</li> +<li><strong>抑制响应(Suppress Response)</strong>:一个标志,用于确定是否应抑制对此操作的<strong>状态响应。</strong></li> +<li><strong>订阅 ID(Subscription ID)</strong>:如果此报告是订阅交易的一部分,它必须包含一个用于识别订阅交易的整数。</li> +</ul> +<h4 id="23-状态响应动作status-response-action">2.3 状态响应动作(Status Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者 -&gt; 目标</strong></p> +</blockquote> +<p>一旦 Initiator 接收到请求的数据,默认情况下它必须生成一个 Status Response Action。此操作由启动器发送,确认已收到报告的数据。如果设置了 Suppress Status Response 标志,则 Initiator 不得发送 Status Response Action。</p> +<p>一旦启动器发送了状态响应操作,或者启动器接收到启用了抑制响应标志的报告数据操作,读取/报告查询就完成了。</p> +<p>状态响应操作仅包含一个<strong>状态字段</strong>,该字段将确认操作成功或显示失败代码。</p> +<h3 id="3-subscription-transaction">3. Subscription Transaction +</h3><h4 id="31-订阅请求操作subscribe-request-action">3.1 订阅请求操作(Subscribe Request Action) +</h4><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>除了单一的读请求动作外,发起者还可以订阅属性或事件的定期更新。因此,同样的报告数据 Action 可以作为订阅交易后的定期数据更新的结果而产生。</p> +<p>订阅交互创建两个节点之间的关系,其中目标定期向发起者生成报告数据操作。 Initiator 是 Subscriber,Target 是 Publisher。</p> +<p>订阅请求操作包含:</p> +<ul> +<li><strong>Min Interval Floor(最小间隔层)</strong>:报告之间的最小间隔。</li> +<li><strong>Max Interval Ceiling(最大区间上限)</strong>:报告之间的最大间隔。</li> +<li>Attribute Reports(属性报告):读取操作请求中请求的零个或多个报告属性的列表。</li> +<li>Event Reports(事件报告):零个或多个报告事件的列表。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141332135.png" +loading="lazy" +></p> +<p>在订阅请求之后,目标用包含第一批报告数据的报告数据操作响应发起者:<strong>Primed Published Data</strong>。</p> +<p>然后,发起者通过发送到目标的状态响应操作来确认报告数据操作。一旦目标接收到一个状态响应动作报告没有错误,它发送一个订阅响应动作。</p> +<p>目标随后将以协商的间隔定期发送报告数据操作,发起者将响应这些操作,直到订阅丢失或取消。</p> +<h4 id="32-订阅响应操作subscribe-response-action">3.2 订阅响应操作(Subscribe Response Action) +</h4><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>这是订阅交易的最后一个操作,并结束了该过程。这包括:</p> +<ul> +<li><strong>Subscription ID(订阅 ID)</strong>:标识订阅的整数。</li> +<li><strong>Min Interval(最小间隔)</strong>:最终确定的报告之间的最小间隔。</li> +<li><strong>Max Interval(最大间隔)</strong>:<em>最终</em>确定<em>的</em>报告之间的最大间隔。</li> +</ul> +<h3 id="4-write-transactions">4. Write Transactions +</h3><h4 id="41-不定时写入事务untimed-write-transaction">4.1 不定时写入事务(Untimed Write Transaction) +</h4><h5 id="411-写请求操作write-request-action">4.1.1 写请求操作(Write Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>与读取请求操作类似,在此操作中,发起者为目标提供:</p> +<ul> +<li><strong>Write Requests(写入请求)</strong>:包含路径和数据的一个或多个元组的列表。</li> +<li><strong>Timed Request(定时请求)</strong>:一个标志,指示此操作是否是定时写入事务的一部分。</li> +<li><strong>Suppress Response(抑制响应)</strong>:指示是否应抑制响应状态操作的标志。</li> +</ul> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141423081.png" +loading="lazy" +></p> +<h5 id="412-写响应操作write-response-action">4.1.2 写响应操作(Write Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<h5 id="413-不定时写入限制untimed-write-restrictions">4.1.3 不定时写入限制(Untimed Write Restrictions) +</h5><p>写入请求动作可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在写请求列表中使用的路径可以包含组,或者它们可以包含通配符,但只在端点字段上。</p> +<h4 id="42-定时写入事务timed-write-transaction">4.2 定时写入事务(Timed Write Transaction) +</h4><p>在定时写入事务中比非定时写入事务多了几个步骤。</p> +<h5 id="421-定时请求操作timed-request-action">4.2.1 定时请求操作(Timed request action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到报告没有错误的 Status Response Action,它将发送 Write Request Action。</p> +<h5 id="422-写请求操作write-request-action">4.2.2 写请求操作(Write Request Action) +</h5><p>与前面描述的 <strong>4.1.1 写请求操作</strong> 相同。</p> +<h5 id="423-写响应操作write-response-action">4.2.3 写响应操作(Write Response Action) +</h5><p>与前面描述的 <strong>4.1.2 写响应操作</strong> 相同。</p> +<h5 id="424-定时写入限制timed-write-restrictions">4.2.4 定时写入限制(Timed Write Restrictions) +</h5><p>定时请求动作、写请求动作和写响应动作是单播的。</p> +<h3 id="5调用事务">5.调用事务 +</h3><p><strong>调用事务</strong>用于在目标节点上调用一个或多个集群命令。它类似于对集群中定义的命令进行的远程过程调用。</p> +<p>与写入事务类似,调用事务支持定时和不定时事务。 有关定时事务的更多信息,请参阅 <strong>交互模型:1.4.定时和非定时</strong></p> +<h4 id="51-不定时调用事务">5.1 不定时调用事务 +</h4><h5 id="511-调用请求操作invoke-request-action">5.1.1 调用请求操作(Invoke Request Action) +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>类似于读请求动作和写请求动作,在这个动作中,发起者为目标提供:</p> +<ul> +<li><strong>Invoke Requests(调用请求):集群命令</strong>的路径(PATH)列表 ,以及命令的可选参数,名为 <strong>Command Fields</strong>。</li> +<li>Timed Request(超时请求):一个标志,指示此操作是否是定时调用事务的一部分。</li> +<li>Suppress Response(抑制响应):指示是否应抑制调用响应操作的标志。</li> +<li><strong>Interaction ID</strong>:一个整数,用于将 Invoke Request Action 与 Invoke Response Action 匹配。</li> +</ul> +<h5 id="512-调用响应操作invoke-response-action">5.1.2 调用响应操作(Invoke Response Action) +</h5><blockquote> +<p><strong>目标 -&gt; 发起者</strong></p> +</blockquote> +<p>目标收到调用请求操作后,它将使用包含以下内容的调用响应操作来完成事务:</p> +<ul> +<li><strong>Invoke Responses(调用响应)</strong>:发送的每个调用请求的命令响应或状态列表。</li> +<li>Interaction ID:一个整数,用于将 Invoke Response Action 与 Invoke Request Action 匹配。</li> +</ul> +<h5 id="513-不定时调用限制">5.1.3 不定时调用限制 +</h5><p>Invoke Request Action可以是一个组播,但在这种情况下,必须设置抑制响应标志。其理由是,否则网络可能会被来自一个组的每个成员的同时响应所淹没。</p> +<p>为了启用这种行为,在调用请求列表中使用的路径可以包含组,或者它们可以包含通配符,但仅在端点字段上。此外,如果行动是组播,这个事务就会在没有响应的情况下终止。</p> +<h4 id="52-定时调用事务">5.2 定时调用事务 +</h4><p>与定时写入事务类似,定时调用事务也从定时请求操作开始。</p> +<h5 id="521-定时请求操作">5.2.1 定时请求操作 +</h5><blockquote> +<p><strong>发起者 -&gt; 目标</strong></p> +</blockquote> +<p>Initiator 启动事务发送此操作,其中包含:</p> +<ul> +<li><strong>Timeout</strong>:此事务可以保持打开状态的毫秒数。在此期间,Initiator 发送的下一个动作将被视为有效。</li> +</ul> +<p>一旦接收到定时请求操作,目标必须使用状态响应操作确认定时请求操作。一旦 Initiator 收到状态响应操作报告没有错误,它将发送调用请求操作。</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306141539988.png" +loading="lazy" +></p> +<h5 id="522-调用请求操作invoke-request-action">5.2.2 调用请求操作(Invoke Request Action) +</h5><p>与前面描述的 <strong>5.1.1 调用请求操作</strong> 相同。</p> +<h5 id="523-调用响应操作invoke-response-action">5.2.3 调用响应操作(Invoke Response Action) +</h5><p>与前面描述的 <strong>5.1.2 调用响应操作</strong> 相同。</p> +<h5 id="524-定时调用限制timed-invoke-restrictions">5.2.4 定时调用限制(Timed Invoke Restrictions) +</h5><p>所有的调用命令都可以在定时交互中调用。定时请求动作、调用请求动作和调用响应动作都是单播的,因此不能在定时调用事务上作为群播使用。</p> +<p>Invoke Request Action支持使用带组的路径,以及通配符,但Invoke Response Action不支持通配符的使用。</p> +<hr> +<h2 id="参考资料">参考资料 +</h2><ul> +<li><a class="link" href="https://developers.home.google.com/matter/primer/device-data-model#parts_list" target="_blank" rel="noopener" +>https://developers.home.google.com/matter/primer/device-data-model#parts_list</a></li> +<li><a class="link" href="https://www.bilibili.com/video/BV1NL411T7Kj/?spm_id_from=333.788&amp;vd_source=40334d7415493efea293dacb3c13f0b4" target="_blank" rel="noopener" +>Matter技术及关键特性介绍</a></li> +</ul>【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul>【Matter】使用chip-tool在ESP32-C3上进行matter开发https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/Tue, 30 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/<img src="https://kurisaw.github.io/p/matter%E4%BD%BF%E7%94%A8chip-tool%E5%9C%A8esp32-c3%E4%B8%8A%E8%BF%9B%E8%A1%8Cmatter%E5%BC%80%E5%8F%91/cover.jpg" alt="Featured image of post 【Matter】使用chip-tool在ESP32-C3上进行matter开发" /><h1 id="使用chip-tool在esp32-c3上进行matter开发">使用chip tool在ESP32-C3上进行matter开发 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><ul> +<li> +<p>请确保你已经能够完成在esp-matter下的应用程序的烧录及串口监视,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130519043?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)</a></p> +</li> +<li> +<p>ubuntu最好使用20以上的版本,因为matter最低需要python3.8的环境</p> +</li> +<li> +<p>PC机需要支持蓝牙4.0及以上版本,如果没有的话需要购买一个USB蓝牙适配器,而且需要支持Linux,可以参考购买这款<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>蓝牙适配器</a></p> +</li> +</ul> +<h2 id="编译-chip-tool">编译 chip-tool +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2编译matter所需环境">2.编译matter所需环境 +</h3><ul> +<li>step1:首先安装编译所需的依赖包:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:切换到 /matter/connectedhomeip/connectedhomeip 目录下,编译matter环境(如果没显示环境过期,这一步可跳过)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 运行引导程序,该脚本负责下载 GN、ninja,并使用用于构建和测试的库设置 Python 环境。如果此脚本显示环境已过期,则可以通过运行以下命令进行更新</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>对于 MacOS,<code>gdbgui</code>python 包不会使用<code>bootstrap.sh</code> 脚本安装,因为它仅限于 x64 Linux 平台。它受到限制,因为在 MacOS 上为<code>gevent</code>(依赖于<code>gdbgui</code>)构建轮子失败。</p> +<p>对于ARM-based Mac,如果Python3版本大于或等于3.11,则不需要进一步的安装步骤。</p> +<p>如果 Python3 版本低于 3.11 或者您使用的是 x86(基于英特尔)Mac,那么请在每次引导后运行以下命令以将 gdbgui wheels 安装为二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">c</span> <span class="n">scripts</span><span class="o">/</span><span class="n">setup</span><span class="o">/</span><span class="n">constraints</span><span class="o">.</span><span class="n">txt</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">cache</span> <span class="o">--</span><span class="n">prefer</span><span class="o">-</span><span class="n">binary</span> <span class="n">gdbgui</span><span class="o">==</span><span class="mf">0.13</span><span class="o">.</span><span class="mf">2.0</span> +</span></span><span class="line"><span class="cl"><span class="n">deactivate</span> +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<ul> +<li>step3:激活编译matter环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">scripts</span><span class="o">/</span><span class="n">activate</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step4:启用 Ccache 以加快 IDF 构建速度</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">$</span> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3构建chip-tool">3.构建CHIP TOOL +</h3><p>在 <code>~/esp/esp-matter/connectedhomeip/connectedhomeip</code>目录下,执行命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">./gn_build.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041738527.png" +loading="lazy" +alt="image-20230504173815084" +></p> +<p>执行完之后,会在根目录下生成 <code>out/debug/standalone/chip-tool</code>一个二进制文件。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041740040.png" +loading="lazy" +alt="image-20230504174038993" +></p> +<p>如果上述命令:<code>./gn_build.sh</code>执行失败,也可以执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scripts</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">gn_build_example</span><span class="p">.</span><span class="n">sh</span> <span class="n">examples</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">SOME</span><span class="o">-</span><span class="n">PATH</span><span class="o">/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041756762.png" +loading="lazy" +alt="image-20230504175634584" +></p> +<p>执行完毕后,在以下路径 <code>connetedhomeip/connectedhomeip/SOME-PATH</code>也可以发现生成了 chip-tool 工具</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041757853.png" +loading="lazy" +alt="image-20230504175700807" +></p> +<h2 id="chip-tool-client-调试设备说明">chip-tool client 调试设备说明 +</h2><p>为了向设备发送命令,必须使用客户端对其进行调试。芯片工具目前<strong>一次只支持调试和记忆一个设备</strong>。配置状态存储在/tmp/chip_tool_config.ini中;</p> +<p>另外删除/tmp中的此文件和其他.ini文件有时可以解决由于过时配置导致的问题。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 获取受支持集群的列表 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nl">Usage</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="o">/</span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">cluster_name</span> <span class="n">command_name</span> <span class="p">[</span><span class="n">param1</span> <span class="n">param2</span> <span class="p">...]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="nl">Clusters</span><span class="p">:</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">barriercontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">basic</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">colorcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">doorlock</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">groups</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">iaszone</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">identify</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">levelcontrol</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">onoff</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">pairing</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">scenes</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">|</span> <span class="o">*</span> <span class="n">temperaturemeasurement</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="o">+-------------------------------------------------------------------------------------+</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041800372.png" +loading="lazy" +alt="image-20230504180042312" +></p> +<ul> +<li><strong>有关具体其他命令和使用方法详见 : <a class="link" href="https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool" target="_blank" rel="noopener" +>https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/chip-tool</a></strong></li> +</ul> +<p>要向设备发起客户端调试请求,需要运行构建的可执行文件并选择配对模式,具体操作如下:</p> +<h3 id="1基于-ble-调试">1.基于 BLE 调试 +</h3><p>运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它。下面的命令使用硬编码到 ESP32 all-clusters-app 调试版本中的默认值来将其调试到 Wi-Fi 网络:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="err">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">SSID</span><span class="p">}</span> <span class="err">$</span><span class="p">{</span><span class="n">PASSWORD</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>${NODE_ID_TO_ASSIGN}</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID。</li> +<li><code>${SSID} 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>${PASSWORD}</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># 例如 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">ble</span><span class="o">-</span><span class="n">wifi</span> <span class="mh">0x7283</span> <span class="n">jetbot</span> <span class="n">jetbotwyq</span> <span class="mi">202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2通过ip与设备配对">2.通过IP与设备配对 +</h3><p>下面的命令将发现设备并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面的命令将根据给定的二维码(哪些设备在启动时记录)发现设备,并尝试与它发现的第一个配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">code</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="n">MT</span><span class="p">:</span><span class="c1">#######</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在所有这些情况下,将为设备分配节点 ID <code>${NODE_ID_TO_ASSIGN}</code> (必须是十进制数或以 0x 为前缀的十六进制数)。</p> +<h3 id="3trust-store">3.Trust store +</h3><p>Trust store 将使用默认的 Test Attestation PAA 自动创建。要使用不同的 PAA 集,请在运行构建的可执行文件时使用可选参数 &ndash;paa-trust-store-path 传递路径。受信任的 PAA 位于 credentials/development/paa-root-certs/。</p> +<p>下面的命令将选择一组受信任的 PAA,以在证明验证期间使用。它还会发现具有长鉴别器 3840 的设备,并尝试使用提供的设置代码与它发现的第一个设备配对。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="k">tool</span> <span class="n">pairing</span> <span class="n">onnetwork</span><span class="o">-</span><span class="n">long</span> <span class="o">$</span><span class="p">{</span><span class="n">NODE_ID_TO_ASSIGN</span><span class="p">}</span> <span class="mi">20202021</span> <span class="mi">3840</span> <span class="o">--</span><span class="n">paa</span><span class="o">-</span><span class="n">trust</span><span class="o">-</span><span class="n">store</span><span class="o">-</span><span class="n">path</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">PAAs</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4忘记当前委托的设备">4.忘记当前委托的设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">chip</span><span class="o">-</span><span class="n">tool</span> <span class="n">pairing</span> <span class="n">unpair</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="使用chip-tool点灯">使用chip-tool点灯 +</h2><h3 id="1matter环境激活">1.matter环境激活 +</h3><p>由于每次配置的 esp-idf 和 esp-matter 环境激活仅在当前终端有效,这里我们编写一个脚本文件,每次打开一个终端执行此脚本即可完成matter环境的激活:</p> +<ul> +<li>step1:新建一个名为 matter.sh 的脚本文件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:复制以下内容到 matter.sh</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#/bin/bash +</span></span></span><span class="line"><span class="cl"><span class="cp"># matter.sh +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="n">EPS_MATTER_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-matter&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">[</span> <span class="err">$</span><span class="mi">1</span> <span class="o">-</span><span class="n">eq</span> <span class="mi">1</span> <span class="p">];</span> <span class="n">then</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_PATH</span><span class="o">=</span><span class="s">&#34;/home/kurisaw/Desktop/esp/esp-gitee-tools/esp-idf&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">source</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span><span class="line"><span class="cl"> <span class="n">export</span> <span class="n">IDF_CCACHE_ENABLE</span><span class="o">=</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">echo</span> <span class="s">&#34;enter matter dir&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cd</span> <span class="err">$</span><span class="n">EPS_MATTER_PATH</span> +</span></span><span class="line"><span class="cl"><span class="n">fi</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:执行脚本以激活 matter 环境</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">source</span> <span class="n">matter</span><span class="p">.</span><span class="n">sh</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2固件烧录">2.固件烧录 +</h3><ul> +<li>打开一个新的<strong>终端1</strong>,进入示例目录设置并编译烧写到评估板运行</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>设置要构建的 Matter 目标</li> +<li>目前所有示例应用程序都支持目标芯片:esp32、esp32s3、esp32c3,一般仅需要使用 命令1 即可。<strong>需要注意的是:如果你使用的设备为ESP32H2,而ESP32H2 仅在 lighting-app 中支持,执行 命令2 将其设置为目标</strong></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 命令1,通用命令,ESP32H2请执行命令2 +</span></span><span class="line"><span class="cl">idf.py set-target (target chip) +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 命令2,ESP32H2专用命令 +</span></span><span class="line"><span class="cl">idf.py --preview set-target esp32h2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是 ESP32C3,所以执行以下命令即可</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>配置选项(可遵循默认配置即可,非特定配置可跳过这一步)</li> +</ul> +<p>要<strong>构建特定配置</strong>(示例<code>m5stack</code>):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rm sdkconfig +</span></span><span class="line"><span class="cl">idf.py -D &#39;SDKCONFIG_DEFAULTS=sdkconfig_m5stack.defaults&#39; build +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:如果使用特定的设备配置,强烈建议从默认设置之一开始并在此基础上进行自定义。某些配置具有在设备特定配置中自定义的不同约束(例如:主应用程序堆栈大小)。</p> +<p>要自定义配置,请运行 menuconfig,在菜单中可完成自定义配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>构建应用程序</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>擦除Flash</li> +</ul> +<p>构建应用程序后,要通过 USB 连接您的设备来闪擦除它。然后运行以下命令擦除整个闪存,将演示应用程序闪存到设备上,然后监控其输出。</p> +<p>请注意,有时您可能必须在设备尝试连接时按住设备上的启动按钮,然后才能刷机。对于 ESP32-DevKitC 设备,这在<a class="link" href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#functional-description" target="_blank" rel="noopener" +>functional description diagram</a>中有所提及。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">idf.py -p (PORT) erase_flash +</span></span><span class="line"><span class="cl">idf.py -p (PORT) flash monitor +</span></span></code></pre></td></tr></table> +</div> +</div><p>请替换<code>(PORT)</code>为您系统的正确 USB 设备名称(如<code>/dev/ttyUSB0</code>在 Linux 或<code>/dev/tty.usbserial-101</code>Mac 上)。</p> +<p>查看USB设备,esp32c3设备名为 <code>ttyUSB0</code>,因此执行以下命令 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">erase_flash</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ttyUSB0</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意此时的设备串口<strong>终端1</strong>暂时先不关闭,后面可使用<code>CTRL+]</code>关闭设备串口调试</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301730041.png" +loading="lazy" +alt="image-20230530173001926" +></p> +<p>注意:某些用户可能必须在设备出现在 /dev/tty 之前安装<a class="link" href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener" +>VCP 驱动程序。</a></p> +<p>提示:在监视器运行时,您可以通过按 Ctrl+t Ctrl+h 来查看各种监视器命令的菜单。</p> +<h3 id="3项目调试">3.项目调试 +</h3><p>以下四种方式可以用于调试在ESP32上运行应用程序:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/controller/python" target="_blank" rel="noopener" +>Python Based Device Controller</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool" target="_blank" rel="noopener" +>Standalone chip-tool</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/darwin/CHIPTool" target="_blank" rel="noopener" +>iOS chip-tool App</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/examples/android/CHIPTool" target="_blank" rel="noopener" +>Android chip-tool App</a></li> +</ul> +<p><strong>注:这里使用 <code>Standalone chip-tool</code>进行项目调试</strong></p> +<p>打开一个新的<strong>终端2</strong>,我们需要运行构建的可执行文件并将远程设备的鉴别器和配对代码以及要使用的网络凭据传递给它,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 激活matter环境</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301723608.png" +loading="lazy" +alt="image-20230530172301207" +></p> +<ul> +<li>调试WIFI设备(ESP32、ESP32C3、ESP32S3)</li> +</ul> +<p>如果你使用的是Thread设备(ESPH2)或以太网设备(ESP32-Ethernet-Kit),设备调试具体可以查看<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>此链接</a></p> +<p>执行下面命令将 matter 设备接入现有现有IP网络,这里我们<strong>基于BLE调试</strong></p> +<p><strong>需要注意的是,你需要确保你的 Linux 蓝牙可用,如果是使用虚拟机的话需要考虑购买一个蓝牙适配器,可参考这个<a class="link" href="https://m.tb.cn/h.UvoJzj4?tk=KpYpdNFRueB" target="_blank" rel="noopener" +>购买链接</a></strong></p> +<p>接下来请按照我的步骤一步步执行:</p> +<ul> +<li>step1:安装 blueman 软件</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install blueman <span class="c1">#安装blueman软件</span> +</span></span><span class="line"><span class="cl">sudo /etc/init.d/bluetooth restart <span class="c1"># 重启blueman服务</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step2:确保你的蓝牙状态处于激活状态</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看蓝牙状态</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo systemctl status bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236623922-496f12f1-837d-44eb-8cca-a76b5f132e2c.png" +loading="lazy" +alt="7e8b531f8b4be994ed272cf2e69703c" +></p> +<p>如果未运行,请执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> bluetooth +</span></span><span class="line"><span class="cl">sudo systemctl start bluetooth +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step3:确认蓝牙适配器已经被识别并启用</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hciconfig -a +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://user-images.githubusercontent.com/98592772/236629771-b49be4da-0979-45b7-9484-f9bb2f895f29.png" +loading="lazy" +alt="LRHC%H77T8AU FZ_V$F@(Q6" +></p> +<p>根据提示信息我们可以得知我的蓝牙适配器名为&quot;hci0&quot;,并且状态为 &ldquo;DOWN&rdquo;,因此我们需要启用该蓝牙适配器。</p> +<ul> +<li>step4:启用蓝牙适配器</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hciconfig hci0 up +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>step5:为了让 matter 设备连接蓝牙网络,我们需要让蓝牙适配器在任何时候可见,点击右上角的蓝牙图标,点击<code>Adapters...---&gt;Visibility Setting---&gt;Always visible</code>,这一步很关键,<strong>每次基于 BLE 调试都需要检查这一步!!</strong></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301744038.png" +loading="lazy" +alt="image-20230530174457873" +></p> +<ul> +<li>step6:BLE调试,回到<strong>终端2</strong>,执行如下命令</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">out/debug/chip-tool pairing ble-wifi 0x7283 jetbot jetbotwyq <span class="m">20202021</span> <span class="m">3840</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:本机ip和matter设备ip必须在同一局域网下</p> +<blockquote> +<ul> +<li><code>0x7283</code>(必须是十进制数或<code>0x</code>- 前缀的十六进制数)是要分配给正在调试的节点的节点 ID,随意填写即可。</li> +<li><code>jetbot 是 Wi-Fi SSID</code> 可以是字符串,也可以是<code>hex:XXXXXXXX</code> SSID 的字节被编码为两位十六进制数字的形式。</li> +<li><code>jetbotwyq</code> 是 Wi-Fi 密码,同样是字符串或十六进制数据</li> +</ul> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301754997.png" +loading="lazy" +alt="image-20230530175437844" +></p> +<p>在<strong>终端1</strong>我们可以看到相关的ip信息:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301756204.png" +loading="lazy" +alt="image-20230530175633102" +></p> +<ul> +<li>step7:利用 chip tool 控制LED开关</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># open led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff on 0x7896 0x1 +</span></span><span class="line"><span class="cl"><span class="c1"># close led</span> +</span></span><span class="line"><span class="cl">out/debug/chip-tool onoff off 0x7896 0x1 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里的节点ID:0x7896需要和前面保持一致</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802687.jpg" +loading="lazy" +alt="cd20c5fede056bf65b089da69ab9f3a" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305301802294.jpg" +loading="lazy" +alt="f40b925710de89f66bf9ecf7ef27d7e" +></p> +<h2 id="chip-tool基于ble调试完整过程">CHIP TOOL基于BLE调试完整过程 +</h2><div class="video-wrapper"> +<video +controls +src="./video.mp4" +autoplay +> +<p> +Your browser doesn't support HTML5 video. Here is a +<a href="./video.mp4">link to the video</a> instead. +</p> +</video> +</div> +<hr> +<h2 id="参考">参考 +</h2><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/chip_tool_guide.md" target="_blank" rel="noopener" +>CHIP Reference</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/setup_idf_chip.md" target="_blank" rel="noopener" +>Setup ESP-IDF and CHIP Environment</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/build_app_and_commission.md" target="_blank" rel="noopener" +>building and commissioning</a></li> +</ul>【Matter】Matter环境构建参考文档https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/Wed, 24 May 2023 00:00:00 +0000https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/<img src="https://kurisaw.github.io/p/mattermatter%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/cover.jpg" alt="Featured image of post 【Matter】Matter环境构建参考文档" /><h1 id="matter-环境构建参考文档">Matter 环境构建参考文档 +</h1><hr> +<p>Matter支持用<a class="link" href="https://gn.googlesource.com/gn/" target="_blank" rel="noopener" +>GN</a>配置构建,一个快速且可扩展的元构建系统,生成输入到<a class="link" href="https://ninja-build.org/" target="_blank" rel="noopener" +>ninja</a>。</p> +<h2 id="经过测试的操作系统">经过测试的操作系统 +</h2><p>该构建系统已经在以下操作系统上进行了测试:</p> +<ul> +<li>macOS 10.15</li> +<li>Debian 11 (64 bit required)</li> +<li>Ubuntu 22.04 LTS</li> +</ul> +<h2 id="构建系统的特点">构建系统的特点 +</h2><p>Matter构建系统有以下特点:</p> +<ul> +<li>速度非常快,占用空间小</li> +<li>跨平台处理: Linux, Darwin, Embedded Arm, 等等</li> +<li>多种工具链和跨工具链的依赖性</li> +<li>集成了自动测试框架: ninja check</li> +<li>自省:&ldquo;gn desc&rdquo;。</li> +<li>自动格式化: <code>gn格式</code>。</li> +</ul> +<h2 id="检查matter的代码">检查Matter的代码 +</h2><p>要检查Matter资源库,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recurse-submodules git@github.com:project-chip/connectedhomeip.git +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="同步子模块">同步子模块 +</h2><p>如果你已经签出了Matter的代码,运行下面的命令来同步子模块:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git submodule update --init +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="先决条件">先决条件 +</h2><p>在构建之前,你必须安装一些操作系统的特定依赖。</p> +<h3 id="1在linux上安装先决条件">1.在Linux上安装先决条件 +</h3><p>在基于Debian的Linux发行版上,如Ubuntu,这些依赖项可以通过以下命令来满足:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev\ +</span></span><span class="line"><span class="cl"> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev +</span></span><span class="line"><span class="cl"> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="用户界面的构建">用户界面的构建 +</h4><p>如果通过<code>build_examples.py</code>和<code>with-ui</code>变体构建,也要安装SDL2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libsdl2-dev +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在macos上安装先决条件">2.在macOS上安装先决条件 +</h3><p>在macOS上,从 Mac App Store上安装 Xcode 。</p> +<h4 id="用户界面的构建-1">用户界面的构建 +</h4><p>如果构建<code>-with-ui</code>变体,也要安装 SDL2 :</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">brew install sdl2 +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3在raspberry-pi-4上安装先决条件">3.在Raspberry Pi 4上安装先决条件 +</h3><p>完成以下步骤:</p> +<ol> +<li>使用:在 micro SD 卡上<code>rpi-imager</code>安装适用于 arm64 架构的 Ubuntu <em>22.04</em> 64 位<em>服务器操作系统。</em></li> +<li>启动SD卡。</li> +<li>用默认的用户账户 &ldquo;ubuntu &ldquo;和密码 &ldquo;ubuntu &ldquo;登录。</li> +<li>继续执行 <a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>在 Linux 上安装先决条件</a>。</li> +<li>安装一些Raspberry Pi的特定依赖项:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install pi-Bluetooth avahi-utils +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="6"> +<li>安装完 &ldquo;pi-bluetooth &ldquo;后,重新启动你的Raspberry Pi。</li> +</ol> +<h4 id="配置wpa_supplicant以存储永久变化">配置wpa_supplicant以存储永久变化 +</h4><p>默认情况下,wpa_supplicant是不允许更新(覆盖)配置的。如果你想让Matter应用程序能够存储配置的变化,您需要进行以下更改:</p> +<ol> +<li>编辑 <code>dbus-fi.w1.wpa_supplicant1.service</code> 文件以使用配置文件来代替,运行以下命令:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/systemd/system/bus-fi.w1.wpa_supplicant1.service +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="2"> +<li>运行以下命令,将wpa_supplicant的启动参数改为提供的值:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="3"> +<li>通过运行以下命令添加<code>wpa-supplicant</code>配置文件:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="4"> +<li>在<code>wpa-supplicant</code>文件中添加以下内容:</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ctrl_interface=DIR=/run/wpa_supplicant +</span></span><span class="line"><span class="cl">update_config=1 +</span></span></code></pre></td></tr></table> +</div> +</div><ol start="5"> +<li>重新启动你的Raspberry Pi。</li> +</ol> +<h2 id="安装zap工具">安装ZAP工具 +</h2><p><code>bootstrap.sh</code>将下载一个兼容的ZAP工具版本并将其设置在<code>$PATH</code>。如果你想安装或使用一个不同版本的工具,你可以从ZAP项目的<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a> 页面下载。</p> +<h3 id="1linux-arm">1.Linux ARM +</h3><p>Zap不提供ARM的二进制版本。Rosetta为Darwin解决了这个问题、然而,对于linux arm,你必须使用本地的ZAP,一般通过设置<code>$ZAP_DEVELOPMENT_PATH</code>(见下面 <code>使用哪种ZAP</code>一节)。</p> +<p>文件<code>scripts/setup/zap.json</code>包含CIPD会下载的版本、所以你可以从zap项目中下载一个兼容的版本<a class="link" href="https://github.com/project-chip/zap/releases" target="_blank" rel="noopener" +>Release</a>。要作为源代码签出代码,相应的标签应该存在于zap中<a class="link" href="https://github.com/project-chip/zap/tags" target="_blank" rel="noopener" +>repository tags</a> 列表中。</p> +<p>命令示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">RUN <span class="nb">set</span> -x <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> mkdir -p /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git clone https://github.com/project-chip/zap.git /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> git checkout <span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm config <span class="nb">set</span> user <span class="m">0</span> <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">&amp;&amp;</span> npm ci +</span></span><span class="line"><span class="cl">ENV <span class="nv">ZAP_DEVELOPMENT_PATH</span><span class="o">=</span>/opt/zap-<span class="si">${</span><span class="nv">ZAP_VERSION</span><span class="si">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2使用哪种zap">2.使用哪种ZAP +</h3><p>ZAP工具脚本使用以下检测,按重要性排序:</p> +<ul> +<li> +<p><code>$ZAP_DEVELOPMENT_PATH</code>指向一个ZAP检出。</p> +</li> +<li> +<p>如果你在本地开发ZAP,并希望用你的改动来运行ZAP和你的改动。</p> +</li> +<li> +<p><code>$ZAP_INSTALL_PATH</code>指向<code>zap-linux.zip</code>或`zap-m</p> +</li> +</ul> +<h2 id="为构建做准备">为构建做准备 +</h2><p>在运行任何其他构建命令之前,<code>scripts/activate.sh</code>的环境设置脚本应该在最高层。这个脚本负责下载GN、ninja,并在Python环境中设置用于构建和测试的库来构建和测试。</p> +<p>运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1更新环境">1.更新环境 +</h3><p>如果脚本说环境已经过期,你可以通过运行下面的命令来更新它:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>脚本 <code>scripts/bootstrap.sh</code>从头开始重新创建环境,这是很昂贵的,所以避免运行它,除非环境已经过期。</p> +<h2 id="为主机操作系统linux或macos进行构建">为主机操作系统(Linux或macOS)进行构建 +</h2><p>运行以下命令,为主机平台构建所有的源代码、库和测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些命令生成了一个适合调试的配置。要配置一个构建,请指定<code>is_debug=false</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/host --args=&#39;is_debug=false&#39; 。 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/host +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**目录名称 &ldquo;out/host &ldquo;可以是任何目录,通常是在<code>out</code>目录下构建。这个例子使用 <code>host</code> 来强调为主机系统构建。不同的构建目录可以用于不同的配置,或者使用一个目录,并在必要时可以根据需要通过<code>gn args</code>重新配置。</p> +</blockquote> +<p>要运行所有测试,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host check +</span></span></code></pre></td></tr></table> +</div> +</div><p>要想只运行<code>src/inet/tests</code>中的测试,可以运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/host src/inet/tests:test_run +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**构建系统会缓存通过的测试,所以你可能会看到以下消息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja: no work to do +</span></span></code></pre></td></tr></table> +</div> +</div><p>这意味着测试在之前的构建中通过了。</p> +</blockquote> +<h2 id="使用build_examplespy">使用<code>build_examples.py</code> +</h2><p>该脚本<code>./scripts/build/build_examples.py</code>提供了一个统一的编译构建接口,可以使用<code>gn</code>、<code>cmake</code>、<code>ninja</code>和其他必要的工具来编译各种平台。</p> +<p>使用 <code>./scripts/build/build_examples.py targets</code> 来查看支持的目标。</p> +<p>构建命令的例子:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># 编译并在主机上运行所有测试: +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 使用 libfuzzer 编译模糊测试标签(模糊测试需要 clang) +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-clang-asan-libfuzzer build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个esp32的例子 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 编译一个 nrf 示例 +</span></span><span class="line"><span class="cl">./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="1libfuzzer单元测试">1.<code>libfuzzer</code>单元测试 +</h3><p><code>libfuzzer</code>单元测试测试只被编译而不被执行(你必须手动执行它们)。为了获得最佳的错误检测,应该使用某种形式的净化器,如<code>asan</code>应该被使用。</p> +<p>可执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build/build_examples.py --target linux-x64-test-lang-asan-libfuzzer build +</span></span></code></pre></td></tr></table> +</div> +</div><p>之后,测试应该被定位在<code>out/linux-x64-tests-lang-asan-libfuzzer/tests/</code>。</p> +<h4 id="ossfuzz的配置"><code>ossfuzz</code>的配置 +</h4><p><code>ossfuzz</code>配置不是独立的模糊测试,而是作为一个与外部模糊测试自动构建的集成点。它们会获取环境变量,如<code>$CFLAGS</code>、<code>$CXXFLAGS</code>和<code>$lib_fuzzing_engine</code>。</p> +<p>你可能需要<code>libfuzzer</code>+<code>asan</code>的构建来代替本地测试。</p> +<h2 id="构建自定义配置">构建自定义配置 +</h2><p>构建是通过设置构建参数来配置的。你可以通过以下方式设置这些参数:</p> +<ul> +<li>将<code>--args</code>选项传递给<code>gn gen</code>。</li> +<li>在输出目录上运行<code>gn args</code>。</li> +<li>编辑输出目录下的<code>args.gn</code>。</li> +</ul> +<p>要配置一个新的构建或编辑现有构建的参数,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn args out/custom +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><p>两个关键的内置构建参数是 <code>target_os</code> 和 <code>target_cpu</code>,它们分别控制构建的操作系统和CPU。</p> +<p>要查看所有可用的构建参数的帮助,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/custom +</span></span><span class="line"><span class="cl">gn args --list out/custom +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="构建实例">构建实例 +</h2><p>你可以通过两种方式构建例子。</p> +<h3 id="1将例子作为独立的项目来构建">1.将例子作为独立的项目来构建 +</h3><p>要把例子作为单独的项目来构建,在Matter的<code>third_party directory</code>,运行下面的命令,输入正确的路径到例子的正确路径(这里是 &ldquo;chip-shell&rdquo;):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd examples/shell +</span></span><span class="line"><span class="cl">gn gen out/debug +</span></span><span class="line"><span class="cl">ninja -C out/debug +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2在顶层建立实例">2.在顶层建立实例 +</h3><p>你可以在Matter项目的顶层构建例子。请看下面的<code>统一构建</code>一节了解详情。</p> +<h2 id="统一构建">统一构建 +</h2><p>要构建一个近似于连续构建集的统一配置,请运行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source scripts/activate.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34;&#39; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ninja -C out/unified all +</span></span></code></pre></td></tr></table> +</div> +</div><p>你可以在改变提交配置之前使用这组命令构建,并测试GCC、Clang、MbedTLS和例子的配置。在一个并行的构建中。每个配置都有一个单独的子目录在输出目录中。</p> +<p>这种统一的构建可以用于日常的开发,尽管为每一次编辑而构建所有的东西会更昂贵。构建每一个编辑项目的成本。为了节省时间,你可以将配置来构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ninja -C out/unified host_gcc +</span></span><span class="line"><span class="cl">ninja -C out/unified check_host_gcc +</span></span></code></pre></td></tr></table> +</div> +</div><p>用配置的名称替换<code>host_gcc</code>,它可以在根目录下的 &ldquo;BUILD.gn &ldquo;中找到。</p> +<p>你也可以用参数对生成的配置进行微调。比如说</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#39;is_debug=true target_os=&#34;all&#34; enable_host_clang_build=false&#39; +</span></span></code></pre></td></tr></table> +</div> +</div><p>完整的列表请参见根目录<code>BUILD.gn</code>。</p> +<p>在统一的构建中,目标有多个实例,需要通过添加通过添加<code>(toolchain)</code>后缀来区分。使用<code>gn ls out/debug</code>来列出所有的目标实例。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">desc</span> <span class="n">out</span><span class="o">/</span><span class="n">unified</span> <span class="s1">&#39;//src/controller(//build/toolchain/host:linux_x64_clang)&#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>**注意:**有些平台可以作为统一构建的一部分来构建需要下载额外的工具。要将这些工具添加到构建中,必须将其位置 +必须作为构建参数提供。例如,要添加 <code>Simplelink cc13x2_26x2</code> 例子到统一构建中,安装<a class="link" href="https://www.ti.com/tool/SYSCONFIG" target="_blank" rel="noopener" +>SysConfig</a> 并添加以下构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn gen out/unified --args=&#34;target_os=\&#34;all\&#34; enable_ti_simplelink_builds=true &gt; ti_sysconfig_root=\&#34;/path/to/sysconfig\&#34;&#34; +</span></span></code></pre></td></tr></table> +</div> +</div></blockquote> +<h2 id="获得帮助">获得帮助 +</h2><p>GN集成了帮助,你可以通过<code>gn help</code>命令访问。</p> +<p>请确保查看以下推荐的主题:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">gn帮助执行</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="err">语法</span> +</span></span><span class="line"><span class="cl"><span class="n">gn</span> <span class="n">help</span> <span class="n">toolchain</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可参见 <a class="link" href="https://gn.googlesource.com/gn/&#43;/master/docs/quick_start.md" target="_blank" rel="noopener" +>快速入门指南</a>。</p> +<h2 id="自省">自省 +</h2><p>GN有各种自省工具来帮助你检查构建配置。下面的例子以<code>out/host</code>输出目录为例:</p> +<ul> +<li> +<p>显示一个输出目录中的所有目标:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn ls out/host +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示所有将被构建的文件:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn output out/host &#39;*&#39; +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示配置的目标的GN表示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/inet --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>将整个构建的GN表示转为JSON格式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host/ &#39;*&#39; --all --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>显示依赖关系树:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //:all deps --tree --all +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>查找依赖性路径:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn path out/host //src/transport/tests:test //src/system +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>列出与`libCHIP&rsquo;连接的有用信息:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gn desc out/host //src/lib include_dirs +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib defines +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib outputs +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"># 一切都是JSON格式 +</span></span><span class="line"><span class="cl">gn desc out/host //src/lib --format=json +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h2 id="覆盖范围">覆盖范围 +</h2><p>代码覆盖率脚本会生成一份报告,其中详细说明了 Matter SDK 源代码的执行量。它还提供了有关 Matter SDK 执行代码段的频率并生成源文件副本的信息,并用执行频率进行了注释。</p> +<p>运行以下命令来启动该脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./scripts/build_coverage.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p>默认情况下,代码覆盖脚本在单元测试级别执行。单元测试由开发人员创建,因此可以让他们最好地了解单元测试中要包含哪些测试。您可以使用以下参数按范围和执行方式扩展覆盖率测试:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> -c, --code 指定收集覆盖数据的范围。 +</span></span><span class="line"><span class="cl"> core&#34;:从Matter SDK的核心堆栈中收集覆盖数据。--default +</span></span><span class="line"><span class="cl"> clusters&#34;:从Matter SDK中的cluster实现中收集覆盖数据。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;:收集Matter SDK的覆盖数据。 +</span></span><span class="line"><span class="cl"> -t, --tests 指定哪些工具来运行覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;unit&#39;: 运行单元测试来驱动覆盖率检查。--default +</span></span><span class="line"><span class="cl"> &#39;yaml&#39;: 运行yaml测试来驱动覆盖率检查。 +</span></span><span class="line"><span class="cl"> &#39;all&#39;: 运行单元和yaml测试来驱动覆盖率检查。 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外,请参阅 Matter SDK 的最新单元测试覆盖率报告(每天收集): <a class="link" href="https://matter-build-automation.ue.r.appspot.com/" target="_blank" rel="noopener" +>matter coverage</a>。</p> +<h2 id="维护事项">维护事项 +</h2><p>如果你对GN构建系统做了任何改变,下一次构建会自动重新生成<code>ninja</code>文件。不需要做任何事情。</p>【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/Sat, 06 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/<img src="https://kurisaw.github.io/p/matteresp-matter%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5%E7%A8%8B%E5%BA%8F%E7%83%A7%E5%BD%95%E5%8F%8A%E4%B8%B2%E5%8F%A3%E7%9B%91%E8%A7%86/cover.jpg" alt="Featured image of post 【Matter】esp-matter环境下的应用实践(程序烧录及串口监视)" /><h1 id="esp-matter环境下的应用实践">esp-matter环境下的应用实践 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><p>请确保你本地已经配置好 <code>esp-idf</code> 及<code>esp-matter</code>环境,可参考此博客<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/130484975?spm=1001.2014.3001.5501" target="_blank" rel="noopener" +>【Matter】esp-matter开发环境搭建</a></p> +<h2 id="设置环境变量">设置环境变量 +</h2><h3 id="1esp-idf">1.ESP-IDF +</h3><p>根据官网提示,我们需要设置linux平台下的标准工具链,安装以下软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早的 Linux 发行版可能需要升级自身的软件源仓库,或开启 backports 套件库,或安装 “cmake3” 软件包(不是安装 “cmake”)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="n">source</span> <span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041609281.png" +loading="lazy" +alt="image-20230504160909004" +></p> +<h3 id="2esp-matter">2.ESP-Matter +</h3><ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-linux" target="_blank" rel="noopener" +>Linux</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>macOS</a></li> +</ul> +<p>由于我们使用的是Linux环境,所以此处仅作Linux下的说明,macOS可详见<a class="link" href="https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-macos" target="_blank" rel="noopener" +>此处</a></p> +<p>在基于 Debian 的 Linux 发行版(例如 Ubuntu)上,可以使用以下命令满足这些依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p>准备编译matter所需环境。注:如切换了其他分支需要重新运行</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/bootstrap.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060133538.png" +loading="lazy" +alt="image-20230506013329415" +></p> +<p>激活编译matter环境</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ./esp/esp-matter/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">source</span> scripts/activate.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041611578.png" +loading="lazy" +alt="image-20230504161123505" +></p> +<h2 id="matter-example编译下载">Matter Example编译下载 +</h2><h3 id="1激活esp-matter环境">1.激活esp-matter环境 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"><span class="p">.</span> <span class="p">.</span><span class="o">/</span><span class="n">export</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2选择esp设备">2.选择esp设备 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>初次执行这个命令发生了如下报错:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">AttributeError</span><span class="p">:</span> <span class="err">&#39;</span><span class="n">HTTPResponse</span><span class="err">&#39;</span> <span class="n">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="err">&#39;</span><span class="n">strict</span><span class="err">&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在GitHub上参考此<a class="link" href="https://github.com/espressif/esp-idf/issues/11340" target="_blank" rel="noopener" +>issue</a>,并执行以下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时重新执行esp-matter安装脚本:</p> +<p>由于需要重新运行安装脚本命令,此处直接执行的话会报错,参考此<a class="link" href="https://github.com/kurisaW/Summer-of-Open-Source/issues/7" target="_blank" rel="noopener" +>issue</a></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="n">connectedhomeip</span><span class="o">/</span><span class="p">.</span><span class="n">environment</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="s">&#34;urllib3&lt;2&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后回到示例工程下继续执行esp设备选择</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时发生了新的错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060221146.png" +loading="lazy" +alt="image-20230506022134054" +></p> +<p>由于示例工程下的build以前遗留的构建文件,而系统在执行程序时并不会覆盖或主动删除旧的构建文件,因此需要用户手动删除,因此正确的操作就是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">rm</span> <span class="o">-</span><span class="n">r</span> <span class="n">esp</span><span class="o">-</span><span class="n">matter</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">light</span><span class="o">/</span><span class="n">build</span> +</span></span><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">set</span><span class="o">-</span><span class="n">target</span> <span class="n">esp32c3</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后成功解决问题:</p> +<p><img src="https://user-images.githubusercontent.com/98592772/236539480-35af78e1-382f-4092-a25b-fb2a09004d0a.png" +loading="lazy" +alt="b372338ad9384db034000d7839549b5" +></p> +<h3 id="3编译工程">3.编译工程 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">build</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060250998.png" +loading="lazy" +alt="image-20230506025001282" +></p> +<h3 id="4sdk烧写">4.SDK烧写 +</h3><p>第一次烧写 SDK 时,需要擦除整个 flash 再执行烧录命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">erase_flash</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060252819.png" +loading="lazy" +alt="image-20230506025047817" +></p> +<p>烧录程序并打开串口监视</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">idf</span><span class="p">.</span><span class="n">py</span> <span class="n">flash</span> <span class="n">monitor</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>可以看到烧录进度:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060251334.png" +loading="lazy" +alt="image-20230506025133178" +></p> +<p>包括串口监视器的提示信息,同时执行以下命令可退出串口监视:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">CTRL</span> <span class="o">+</span> <span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305060254172.png" +loading="lazy" +alt="image-20230506025401001" +></p> +<p>那么esp-matter项目环境的编译下载就先讲到这里,后面再进行详细的使用教程的讲解。</p> +<hr> +<p>参考链接:</p> +<p><a class="link" href="https://blog.csdn.net/hydfxy2018/article/details/122041168?spm=1001.2101.3001.6650.11&amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-122041168-blog-127516686.pc_relevant_default&amp;utm_relevant_index=12" target="_blank" rel="noopener" +>Matter Over Wifi 例程体验(CHIP Over Wifi)</a></p> +<p><a class="link" href="https://blog.csdn.net/weixin_40209493/article/details/125814311?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168324979316800211536064%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=168324979316800211536064&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-125814311-null-null.142%5ev86%5econtrol_2,239%5ev2%5einsert_chatgpt&amp;utm_term=matter%E6%8A%A5%E9%94%99&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>ESP-Matter 环境测试</a></p> +<p><a class="link" href="https://blog.csdn.net/puweiqi/article/details/129474079?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-129474079-blog-125973073.235%5Ev32%5Epc_relevant_default_base3&amp;utm_relevant_index=3" target="_blank" rel="noopener" +>matter搭建环境</a></p> +<p><a class="link" href="https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html" target="_blank" rel="noopener" +>https://docs.espressif.com/projects/esp-matter/en/main/esp32/developing.html</a></p>【Matter】esp-matter开发环境搭建https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Thu, 04 May 2023 00:00:00 +0000https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/matteresp-matter%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【Matter】esp-matter开发环境搭建" /><h1 id="esp-matter开发环境搭建">esp-matter开发环境搭建 +</h1><hr> +<h2 id="前提准备">前提准备 +</h2><h3 id="1ubuntu2204磁盘容量不小于80g">1.Ubuntu22.04(磁盘容量不小于80G) +</h3><h3 id="2科学上网环境">2.科学上网环境 +</h3><p>由于后面的 esp-matter 测试的时候需要使用到科学上网环境,所以我们需要提前确保 linux 环境能够使用科学上网。</p> +<p>参考链接:<a class="link" href="https://kurisaw.github.io/p/%e7%bb%8f%e9%aa%8c%e5%88%86%e4%ba%ablinux-%e7%8e%af%e5%a2%83%e4%b8%8bv2ray%e7%9a%84%e4%bd%bf%e7%94%a8/" target="_blank" rel="noopener" +>【经验分享】Linux 环境下v2ray的使用</a></p> +<h2 id="esp-idf-开发环境搭建">esp-idf 开发环境搭建 +</h2><h3 id="1esp-idf-依赖环境安装">1.ESP-IDF 依赖环境安装 +</h3><blockquote> +<p>参考https://docs.espressif.com/projects/esp-idf/en/v4.4.3/esp32/get-started/linux-setup.html</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">git</span> <span class="n">wget</span> <span class="n">flex</span> <span class="n">bison</span> <span class="n">gperf</span> <span class="n">python3</span> <span class="n">python3</span><span class="o">-</span><span class="n">pip</span> <span class="n">python3</span><span class="o">-</span><span class="n">setuptools</span> <span class="n">cmake</span> <span class="n">ninja</span><span class="o">-</span><span class="n">build</span> <span class="n">ccache</span> <span class="n">libffi</span><span class="o">-</span><span class="n">dev</span> <span class="n">libssl</span><span class="o">-</span><span class="n">dev</span> <span class="n">dfu</span><span class="o">-</span><span class="n">util</span> <span class="n">libusb</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于在克隆官方esp-idf仓库的时候一般会发生如下两个错误:</p> +<ul> +<li>Problem1:执行 git submodule 速度慢</li> +<li>Problem2:执行install.sh 速度慢</li> +</ul> +<p>所以我们这里特别着重讲解,注意,这里解决问题的顺序与esp-idf环境搭建是一起进行的,读者可以顺着流程走。</p> +<h3 id="2problem1-solution">2.Problem1 solution +</h3><p>首先使用递归克隆命令克隆整个仓库到文件夹下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">kurisaw</span><span class="o">/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-idf.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">submodule</span> <span class="n">update</span> <span class="o">--</span><span class="n">init</span> <span class="o">--</span><span class="n">recursive</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>由于 esp-idf 仓库下有很多递归的下游仓库,一般使用 GitHub 下载的话也会导致递归下载失败,所以乐鑫官方提供了两种解决方案,包括镜像仓库使用、submodule 更新、开发工具安装等,可加速环境的搭建。解决方案如下:</p> +<ul> +<li>jihu-mirror 使用(推荐)</li> +<li>submodule-update 使用(不推荐)</li> +</ul> +<h4 id="21--jihu-mirror-使用推荐">2.1 jihu-mirror 使用(推荐) +</h4><ul> +<li>Step 1:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-gitee-tools.git +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Step 2:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 使用如下命令将仓库的 URL 进行替换: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">url</span><span class="p">.</span><span class="nl">https</span><span class="p">:</span><span class="c1">//jihulab.com/esp-mirror/espressif/esp-idf.insteadOf https://github.com/espressif/esp-idf +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>当我们使用命令 <code>git clone https://github.com/espressif/esp-idf</code> 时,默认的 URL <code>https://github.com/espressif/esp-idf</code> 将被自动替换成 <code>https://jihulab.com/esp-mirror/espressif/esp-idf</code>。</p> +<ul> +<li>Step 3:</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 启用镜像URL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">set</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用命令 <code>./jihu-mirror.sh unset</code> 恢复,不使用镜像的 URL。</p> +<ul> +<li>Step 4:当使用镜像 URL 之后,再递归克隆 esp-idf 仓库</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git clone --recursive https://github.com/espressif/esp-idf.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然如果不想使用镜像的URL可以使用如下命令进行恢复:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">jihu</span><span class="o">-</span><span class="n">mirror</span><span class="p">.</span><span class="n">sh</span> <span class="n">unset</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="22--submodule-update-使用不推荐">2.2 submodule-update 使用(不推荐) +</h4><ul> +<li> +<p>Step 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">gitee</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">EspressifSystems</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span><span class="o">.</span><span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>Step 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 仅克隆 esp-idf,不包含子模块 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//gitee.com/EspressifSystems/esp-idf.git +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<ul> +<li>Step 3:</li> +</ul> +<p>可以有两种方式来更新 submodules。</p> +<ul> +<li> +<p>方式一</p> +<p>进入 esp-gitee-tools 目录,export submodule-update.sh 所在路径,方便后期使用,如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="k">export</span> <span class="n">EGT_PATH</span><span class="o">=$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入 esp-idf 目录执行 submodule-update.sh 脚本:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd esp-idf +</span></span><span class="line"><span class="cl">$EGT_PATH/submodule-update.sh +</span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<p>方式二</p> +<p><code>submodule-update.sh</code> 脚本支持将待更新 submodules 的工程路径作为参数传入,例如:<code>submodule-update.sh PATH_OF_PROJ</code>。</p> +<p>假如 Step 2 中 clone 的 esp-idf 位于 ~/git/esp32-sdk/esp-idf 目录,可使用以下方式来更新:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">cd</span> <span class="n">esp</span><span class="o">-</span><span class="n">gitee</span><span class="o">-</span><span class="n">tools</span> +</span></span><span class="line"><span class="cl"><span class="o">./</span><span class="n">submodule</span><span class="o">-</span><span class="n">update</span><span class="o">.</span><span class="n">sh</span> <span class="o">~/</span><span class="n">git</span><span class="o">/</span><span class="n">esp32</span><span class="o">-</span><span class="n">sdk</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果要更新其他工程,可以同样方式。</p> +</li> +</ul> +<blockquote> +<p>值得吐槽的是, submodule-update 这种方法还需要保持上游代码分支的提交历史一致,如果官方未及时更新则会导致该脚本暂时失效,不推荐使用,避坑!!</p> +</blockquote> +<h3 id="3problem2-solution">3.Problem2 solution +</h3><p>下面说第二个问题:执行./install.sh速度慢的问题</p> +<p>在 Espressif Systems 的 esp-idf 开发框架中,某些组件的构建过程需要从 GitHub 的 release 页面下载预编译的二进制文件。然而,在中国大陆访问 GitHub 的速度往往较慢并且不稳定,为了改善这个问题,Espressif Systems 将这些预编译的二进制文件托管在国内的服务器上,并提供了一个名为 <code>IDF_GITHUB_ASSETS</code> 的环境变量来指定这个地址。在设置了 <code>IDF_GITHUB_ASSETS</code> 变量之后,构建过程将会从这个指定的地址下载预编译的二进制文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">export</span> <span class="n">IDF_GITHUB_ASSETS</span><span class="o">=</span><span class="s">&#34;dl.espressif.com/github_assets&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后再执行安装命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这还报了一个错误</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041247286.png" +loading="lazy" +alt="image-20230504124717772" +></p> +<p>我们根据提示安装<code>python3.10-venv</code>,并再次执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="mf">.10</span><span class="o">-</span><span class="n">venv</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041249721.png" +loading="lazy" +alt="image-20230504124913620" +></p> +<p>至此,esp-idf 的安装工具就告一段落了。</p> +<h2 id="esp-matter开发环境搭建-1">esp-matter开发环境搭建 +</h2><blockquote> +<p>参考:<a class="link" href="https://github.com/espressif/esp-matter" target="_blank" rel="noopener" +>【乐鑫 Matter SDK GitHub】</a></p> +</blockquote> +<p>**注意:如果上面的 esp-idf 开发环境的搭建使用的是 jihu-mirror 方式,那么你需要取消esp镜像,按理说这部分错误不应该发生,但实际上确实存在这部分问题,请执行命令:<code>./jihu-mirror.sh unset</code>取消esp镜像!! **</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">git</span> <span class="n">clone</span> <span class="o">--</span><span class="n">recursive</span> <span class="nl">https</span><span class="p">:</span><span class="c1">//github.com/espressif/esp-matter.git +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>若过程有报错,请执行下面命令在Git 仓库中获取到所有子模块,并将所有子模块及其下层子模块更新至最新版本。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git submodule update --init --recursive +</span></span></code></pre></td></tr></table> +</div> +</div><p>执行安装命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>本以为到这就结束了,但不出意外的话意外发生了,在安装过程中发生了报错&hellip;</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): started +</span></span><span class="line"><span class="cl"> error: subprocess-exited-with-error +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> × python setup.py bdist_wheel did not run successfully. +</span></span><span class="line"><span class="cl"> │ exit code: 1 +</span></span><span class="line"><span class="cl"> ╰─&gt; See above for output. +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> note: This error originates from a subprocess, and is likely not a problem with pip. +</span></span><span class="line"><span class="cl"> Building wheel for pycryptodome (setup.py): finished with status &#39;error&#39; +</span></span><span class="line"><span class="cl"> ERROR: Failed building wheel for pycryptodome +</span></span><span class="line"><span class="cl"> Running setup.py clean for pycryptodome +</span></span><span class="line"><span class="cl"> Building wheel for gevent (pyproject.toml): started +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ...... +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们查看<code>install.sh</code>文件</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nv">basedir</span><span class="o">=</span><span class="k">$(</span>dirname <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">ESP_MATTER_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">;</span> <span class="nb">pwd</span><span class="k">)</span> +</span></span><span class="line"><span class="cl"><span class="nv">MATTER_PATH</span><span class="o">=</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip +</span></span><span class="line"><span class="cl"><span class="nb">export</span> ESP_MATTER_PATH +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Running Matter Setup&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/scripts/bootstrap.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Run the zap_download.py and extract the path of installed binary</span> +</span></span><span class="line"><span class="cl"><span class="c1"># eg output before cut: &#34;export ZAP_INSTALL_PATH=zap/zap-v2023.03.06-nightly&#34;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># output after cut: zap/zap-v2023.03.06-nightly</span> +</span></span><span class="line"><span class="cl"><span class="c1"># TODO: Remove the zap-version after https://github.com/project-chip/connectedhomeip/pull/25727 merged</span> +</span></span><span class="line"><span class="cl"><span class="nv">zap_path</span><span class="o">=</span><span class="sb">`</span>python3 <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip/scripts/tools/zap/zap_download.py <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --sdk-root <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/connectedhomeip/connectedhomeip --zap RELEASE --zap-version v2023.03.27-nightly <span class="se">\ +</span></span></span><span class="line"><span class="cl"><span class="se"></span> --extract-root .zap 2&gt;/dev/null <span class="p">|</span> cut -d<span class="o">=</span> -f2<span class="sb">`</span> +</span></span><span class="line"><span class="cl"><span class="c1"># Check whether the download is successful.</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="nv">$zap_path</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Failed to install zap-cli&#34;</span> +</span></span><span class="line"><span class="cl"> deactivate +</span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># Move files to one directory up, so that binaries will be in $ESP_MATTER_PATH/.zap/ directory and export.sh can leverage the fixed path</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span><span class="s2">/.zap&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> +</span></span><span class="line"><span class="cl"> rm -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl"><span class="k">fi</span> +</span></span><span class="line"><span class="cl">mkdir <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap +</span></span><span class="line"><span class="cl">mv <span class="nv">$zap_path</span>/* <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/ +</span></span><span class="line"><span class="cl">rm -r <span class="nv">$zap_path</span> +</span></span><span class="line"><span class="cl">chmod +x <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/.zap/zap-cli +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Building host tools&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">gn --root<span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">&#34;</span> gen <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl">ninja -C <span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span>/out/host +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Host tools built at: </span><span class="si">${</span><span class="nv">MATTER_PATH</span><span class="si">}</span><span class="s2">/out/host&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Exit Matter environment&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">deactivate +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for mfg_tool&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/tools/mfg_tool/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Installing python dependencies for Matter&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl">python3 -m pip install -r <span class="si">${</span><span class="nv">ESP_MATTER_PATH</span><span class="si">}</span>/requirements.txt +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;All done! You can now run:&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34; . </span><span class="si">${</span><span class="nv">basedir</span><span class="si">}</span><span class="s2">/export.sh&#34;</span> +</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现问题出在第10到13行,我尝试安装系统必要的依赖项来解决这个问题,成功解决!命令如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install build-essential python3-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pkg-config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libglib2.0-dev libglib2.0-dev-bin libgio2.0-cil-dev +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041452447.png" +loading="lazy" +alt="image-20230504145216015" +></a></p> +<p>接着在安装<code>zap-cli</code>的时候再次发生报错,需要安装以下依赖库,并再次运行安装脚本命令,等待编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">./install.sh +</span></span></code></pre></td></tr></table> +</div> +</div><p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041502605.png" +loading="lazy" +alt="image-20230504150238105" +></a></p> +<p>最后看到<code>All done!</code>即代表环境安装成功!</p> +<p><a class="link" href="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" target="_blank" rel="noopener" +><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202305041535612.png" +loading="lazy" +alt="image-20230504153243388" +></a></p> +<p>至此,esp-matter开发环境搭建成功!</p> \ No newline at end of file diff --git a/tags/matter/page/1/index.html b/tags/matter/page/1/index.html new file mode 100644 index 000000000..aa08c08d8 --- /dev/null +++ b/tags/matter/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/matter/ + \ No newline at end of file diff --git a/tags/matter/page/2/index.html b/tags/matter/page/2/index.html new file mode 100644 index 000000000..19da400ea --- /dev/null +++ b/tags/matter/page/2/index.html @@ -0,0 +1,56 @@ +Tag: Matter - Pager 2 - kurisaW +

Tags

8 pages

Matter

\ No newline at end of file diff --git a/tags/mcu/index.html b/tags/mcu/index.html new file mode 100644 index 000000000..d5e2a1319 --- /dev/null +++ b/tags/mcu/index.html @@ -0,0 +1,55 @@ +Tag: MCU - kurisaW +

Tags

1 page

MCU

\ No newline at end of file diff --git a/tags/mcu/index.xml b/tags/mcu/index.xml new file mode 100644 index 000000000..8e4746dad --- /dev/null +++ b/tags/mcu/index.xml @@ -0,0 +1,10 @@ +MCU on kurisaWhttps://kurisaw.github.io/tags/mcu/Recent content in MCU on kurisaWHugo -- gohugo.ioenSat, 04 Nov 2023 00:00:00 +0000【嵌入式素养提升】MPU与MCUhttps://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/<img src="https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover.jpg" alt="Featured image of post 【嵌入式素养提升】MPU与MCU" /><h2 id="mpu与mcu">MPU与MCU +</h2><p>MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。</p> +<p>但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。</p> +<p>在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。</p> +<p>由于主要完成“控制”相关的任务,所以称为 <code>Controller</code>。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。</p> +<p>而<code>Processor</code>,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。</p> +<p>以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。</p> +<p>为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。</p> +<p>从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。</p> +<p>总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。</p> \ No newline at end of file diff --git a/tags/mcu/page/1/index.html b/tags/mcu/page/1/index.html new file mode 100644 index 000000000..6080e5820 --- /dev/null +++ b/tags/mcu/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/mcu/ + \ No newline at end of file diff --git a/tags/micro_ros/index.html b/tags/micro_ros/index.html new file mode 100644 index 000000000..6082f641a --- /dev/null +++ b/tags/micro_ros/index.html @@ -0,0 +1,55 @@ +Tag: Micro_ROS - kurisaW +

Tags

1 page

Micro_ROS

\ No newline at end of file diff --git a/tags/micro_ros/index.xml b/tags/micro_ros/index.xml new file mode 100644 index 000000000..89dd12669 --- /dev/null +++ b/tags/micro_ros/index.xml @@ -0,0 +1,472 @@ +Micro_ROS on kurisaWhttps://kurisaw.github.io/tags/micro_ros/Recent content in Micro_ROS on kurisaWHugo -- gohugo.ioenThu, 26 Oct 2023 00:00:00 +0000【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul> \ No newline at end of file diff --git a/tags/micro_ros/page/1/index.html b/tags/micro_ros/page/1/index.html new file mode 100644 index 000000000..b97c1d45c --- /dev/null +++ b/tags/micro_ros/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/micro_ros/ + \ No newline at end of file diff --git a/tags/micropython/index.html b/tags/micropython/index.html new file mode 100644 index 000000000..4894b0749 --- /dev/null +++ b/tags/micropython/index.html @@ -0,0 +1,55 @@ +Tag: MicroPython - kurisaW +

Tags

1 page

MicroPython

\ No newline at end of file diff --git a/tags/micropython/index.xml b/tags/micropython/index.xml new file mode 100644 index 000000000..d66b30ed2 --- /dev/null +++ b/tags/micropython/index.xml @@ -0,0 +1,215 @@ +MicroPython on kurisaWhttps://kurisaw.github.io/tags/micropython/Recent content in MicroPython on kurisaWHugo -- gohugo.ioenMon, 06 Feb 2023 00:00:00 +0000【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul> \ No newline at end of file diff --git a/tags/micropython/page/1/index.html b/tags/micropython/page/1/index.html new file mode 100644 index 000000000..722c6cf50 --- /dev/null +++ b/tags/micropython/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/micropython/ + \ No newline at end of file diff --git a/tags/mpu/index.html b/tags/mpu/index.html new file mode 100644 index 000000000..e8de56a48 --- /dev/null +++ b/tags/mpu/index.html @@ -0,0 +1,55 @@ +Tag: MPU - kurisaW +

Tags

1 page

MPU

\ No newline at end of file diff --git a/tags/mpu/index.xml b/tags/mpu/index.xml new file mode 100644 index 000000000..91e4dfd8f --- /dev/null +++ b/tags/mpu/index.xml @@ -0,0 +1,10 @@ +MPU on kurisaWhttps://kurisaw.github.io/tags/mpu/Recent content in MPU on kurisaWHugo -- gohugo.ioenSat, 04 Nov 2023 00:00:00 +0000【嵌入式素养提升】MPU与MCUhttps://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/Sat, 04 Nov 2023 00:00:00 +0000https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/<img src="https://kurisaw.github.io/p/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87mpu%E4%B8%8Emcu/cover.jpg" alt="Featured image of post 【嵌入式素养提升】MPU与MCU" /><h2 id="mpu与mcu">MPU与MCU +</h2><p>MPU全名称为 Micro processor Unit,MCU全称为Micro Controller Uint,首先这两个词都带有一个Micro开头,这就表明了这是计算、控制单元小型化后出现的技术,由于集成电路进步带来的计算机系统集成程度提高的结果,是的原来有多片分化的组成的计算机系统向高度集成化发展,多个芯片或元件的功能在向一颗芯片集中,这也是一个大的技术演进的背景。</p> +<p>但是在这种技术的演进过程中,出现了两种不同的需求:“以软制硬”和“以硬助软”。所谓以软制硬,就是通过一段软件程序来控制硬件,也就是所谓的“程控”,在这种使用模式下,计算机系统不承担主要的工作负载,而主要起辅助、协调、控制作用。</p> +<p>在这种情况下集成化的计算机系统就不需要太强大的计算、处理能力,所以对应的形态应该是运行频率低、运算能力一般,但是需要集成化的程度高(使用方便)、价格低廉(辅助系统不应该增加太多成本)等因素。</p> +<p>由于主要完成“控制”相关的任务,所以称为 <code>Controller</code>。也就是根据外界信号(刺激),产生一些响应,做点简单的人机界面。对于这种需求,通常不需要芯片主频太高。在早期的8051系列主频不过是10几MHZ,还是12个周期执行一条指令。而经过多年的“魔改”,最终也达到了100MHZ。其次就是处理能力不强,8位的MCU长期是微控制器的主流,而后来16位的MCU逐步开始占领市场,随着ARM的32位MCU的出现,采用ARM的M系列MCU也开始逐步扩大市场,并以ST、NXP公司的产品为主要代表。但是这些ARM的M系列MCU的主频一般也是在几十MHZ和100多MHZ的量级。再然后由于执行的“控制相关”的任务,通常不需要支持负载的图形界面和处理能力。在MCU上完成的任务大多数情况下是一些简单的刺激-响应式的任务,而且任务类型单一,任务执行过程简单。在这种情况下一般不需要MCU去执行功能复杂、运算量大的程序,因此通过也不需要运行大型操作系统来支持复杂的多任务管理,这就造成了MCU一般对于存储器的容量要求比较低。</p> +<p>而<code>Processor</code>,顾名思义就是处理器。处理器就是能够执行“处理”功能的器件,其实具备Processor 这个单词的器件不少,比如CPU就成为“中央处理器”,那既然有“中央”就应该有“外围”。GPU在经典的桌面计算机中就是一个典型的“外围”设备,主要负责图形图像处理。</p> +<p>以上对处理器说了这么多,核心意思就是一个,处理器一定要处理/运算能力强,能够执行比较复杂的任务;而微处理器,其实就是微型化/集成化了的处理器,标准来说是微型化/集成化的“中央处理器”,这就是把传统的CPU之外继承了原属于“芯片组”的各类接口和部分“外设”而形成的。MPU从一开始就定位了具备相当的处理和运算能力,一般需要运行较大的操作系统来实现复杂的任务处理。因此这就决定了MPU应该具备比较高的主频和较为强大的运算能力。</p> +<p>为了支撑MPU强大的算力,是的“物尽其用”,必然要求在MPU上运行比较复杂的、运算量大的程序和任务,通常需要有大容量的存储器来配合支撑。而大容量的存储器难以被集成到以逻辑功能为主的MPU内部,因此通常需要“外挂”大容量的存储器,主要是大容量的DDR存储器和FLASH,在手机领域,前者被称为“运存”,而后者被称之为“内存”,为了支撑运行复杂操作系统和大型程序,往往还需要MPU中集成高性能的存储控制器、存储管理单元(MMU)等一套复杂的存储机制和硬件。</p> +<p>从形态上看,MPU由于需要运行对处理能力要求复杂的大程序,一般都需要外挂存储器才能运行起来。而MCU往往只是执行刺激-响应式的过程控制和辅助,功能比较单一,仅仅需要使用偏上集成的小存储器即可。这是区分MPU和MCU的重要表象,但不是核心原因。</p> +<p>总结一下,MPU和MCU的区别本质上是因为应用定位的不同,为了满足不同的应用场景而按不同方式优化出来的两类器件。MPU注重通过较为强大的运算/处理能力,执行复杂多样的大型程序,通常需要外挂大容量的存储器。而MCU通常运行比较单一的任务,执行对于硬件设备的管理/控制功能,通常不需要很强的运算/处理能力,因此也不需要有大容量的存储器来支撑运行大程序,通常以单片机集成的方式在单个芯片内部集成小容量的存储器实现系统的“单片化”。</p> \ No newline at end of file diff --git a/tags/mpu/page/1/index.html b/tags/mpu/page/1/index.html new file mode 100644 index 000000000..aa1b8796d --- /dev/null +++ b/tags/mpu/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/mpu/ + \ No newline at end of file diff --git a/tags/nordic/index.html b/tags/nordic/index.html new file mode 100644 index 000000000..644e24639 --- /dev/null +++ b/tags/nordic/index.html @@ -0,0 +1,55 @@ +Tag: Nordic - kurisaW +

Tags

1 page

Nordic

\ No newline at end of file diff --git a/tags/nordic/index.xml b/tags/nordic/index.xml new file mode 100644 index 000000000..221222bec --- /dev/null +++ b/tags/nordic/index.xml @@ -0,0 +1,138 @@ +Nordic on kurisaWhttps://kurisaw.github.io/tags/nordic/Recent content in Nordic on kurisaWHugo -- gohugo.ioenWed, 07 Jun 2023 00:00:00 +0000【Matter】Nordic-Mattter开发大纲https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/Wed, 07 Jun 2023 00:00:00 +0000https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/<img src="https://kurisaw.github.io/p/matternordic-mattter%E5%BC%80%E5%8F%91%E5%A4%A7%E7%BA%B2/cover.jpg" alt="Featured image of post 【Matter】Nordic-Mattter开发大纲" /><h2 id="nrf-connect-sdk-支持mattter">nRF Connect SDK 支持Mattter +</h2><ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/index.html" target="_blank" rel="noopener" +>Nordic提供的Matter用户指南</a></li> +</ul> +<blockquote> +<p>子页面:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/index.html" target="_blank" rel="noopener" +>Matter概况</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/index.html" target="_blank" rel="noopener" +>开始使用Matter</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/end_product/index.html" target="_blank" rel="noopener" +>如何创建 Matter 最终产品</a></li> +</ul> +</blockquote> +<h2 id="matter网络拓扑结构">Matter网络拓扑结构 +</h2><p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306012004778.png" +loading="lazy" +alt="image-20230601200431602" +></p> +<ul> +<li><code>Thread</code>:Thread是一种开放的低功耗无线通信协议,旨在为物联网设备提供安全、稳定、高效的IPv6连接。它基于IEEE 802.15.4标准,支持多种应用场景,如智能家居、建筑自动化、工业自动化等。Thread协议的特点是易于扩展、安全性高、可靠性好、覆盖范围广、低功耗等。</li> +<li><code>WI-FI</code>:Wi-Fi是一种无线局域网技术,采用IEEE 802.11标准,可以实现高速的无线数据传输。它广泛应用于智能手机、平板电脑、笔记本电脑、智能家居、智能电视等设备中,可以通过无线方式连接互联网和其他设备。Wi-Fi的主要特点是速度快、覆盖范围广、使用方便等。</li> +<li><code>Ethernet(以太网)</code>:Ethernet(以太网)是一种有线局域网技术,采用IEEE 802.3标准,可以通过网线连接设备和网络。它是一种广泛应用于计算机网络中的技术,可以实现高速的数据传输和可靠的网络连接。Ethernet的主要特点是速度快、可靠性高、稳定性好等。</li> +<li><code>Matter binding(Matter协议)</code>:Matter是一个由智能家居设备制造商、芯片厂商和互联网巨头等多个公司发起的开放性联盟,旨在促进智能家居设备之间的互操作性和互连性。Matter协议是该联盟发布的一种通信协议,可以让智能家居设备之间相互通信和交互。Matter协议的特点是开放性强、互操作性好、安全性高、可扩展性强等。Matter binding是指将Matter协议与其他通信协议(如蓝牙、Wi-Fi等)进行绑定,实现智能家居设备之间的互连和互操作。</li> +</ul> +<h2 id="硬件平台">硬件平台 +</h2><p>运行 Matter 协议应用程序的硬件必须满足规范要求,包括提供适量的闪存以及能够同时运行蓝牙 LE 和 Thread 或 Wi-Fi。</p> +<blockquote> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/hw_requirements.html" target="_blank" rel="noopener" +>硬件参考</a></p> +</blockquote> +<ul> +<li>Nodic nRF52840</li> +<li>PC: Ubuntu(20.04 或更新版本)</li> +<li>Raspberry Pi 4(以及内存至少为 8 GB 的 SD 卡)</li> +<li>支持 IPv6 的 Wi-Fi 接入点(路由器上未启用 IPv6 路由器广告防护)</li> +<li>RF52840 DK 或 nRF52840 Dongle - 用于无线电协处理器 (RCP) 设备</li> +<li>兼容 Nordic Semiconductor 的 DK - 用于 Matter 附件设备(与其中一个<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>兼容并编程)</li> +</ul> +<h2 id="软件平台">软件平台 +</h2><p>Linux PC withsoftware installed:</p> +<ul> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/getting_started.html" target="_blank" rel="noopener" +>nRFConnectSDK v2.1.1</a></p> +</li> +<li> +<p><a class="link" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download" target="_blank" rel="noopener" +>nRFCommand-line tools</a></p> +</li> +<li> +<p><a class="link" href="https://nrfconnect.github.io/vscode-nrf-connect/" target="_blank" rel="noopener" +>Visual Studio Code withnRFConnect ExtensionPack for VS Code </a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_thread_tools.html#installing-otbr-manually-raspberry-pi" target="_blank" rel="noopener" +>RaspberryPi 4 runningOpenThreadBorder Router</a></p> +</li> +</ul> +<h2 id="商业matter生态系统测试方式">商业Matter生态系统测试方式 +</h2><p>对于matter设备在不同协议下的配置和使用,官方提供以下几种方式:</p> +<ul> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_separate_otbr_linux_macos.html" target="_blank" rel="noopener" +>Matter over Thread:在不同的设备上配置边界路由器和 Linux/macOS 控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a></li> +<li><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/wifi_pc.html" target="_blank" rel="noopener" +>Matter over Wi-Fi:为 Linux 或 macOS 配置 CHIP 工具</a></li> +</ul> +<p><strong>注意:这里我们基于<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread:在一台设备上配置边界路由器和控制器</a>进行过程演示。</strong></p> +<hr> +<h2 id="matter-over-thread在一台设备上配置边界路由器和控制器">Matter over Thread::在一台设备上配置边界路由器和控制器 +</h2><p>如果你只有一台设备,无论是装有 Linux 的 PC 还是 Raspberry Pi,你都可以设置和测试 Matter over Thread 开发环境,同时在这台设备上运行 Thread Border Router 和 Matter 控制器。</p> +<p>在此设置中,PC 或 Raspberry Pi 同时运行 Thread Border Router 和适用于 Linux 或 macOS 的 CHIP 工具。为了简化 Thread 与 Matter 附件设备的通信,使用带有 OpenThread Border Router 图像的 Docker 容器,而不是本地安装 OpenThread Border Router。</p> +<p>下面是在同一台设备上设置 OpenThread Board Router 和 Matter 控制器的拓扑结构图,我们结合 CHIP TOOL 进行开发</p> +<p><img src="https://cdn.jsdelivr.net/gh/kurisaW/picbed/img2023/202306052053960.png" +loading="lazy" +alt="image-20230605205336833" +></p> +<h3 id="1要求">1.要求 +</h3><p>若要使用此设置,需要以下硬件:</p> +<ul> +<li>以下任意之一: +<ul> +<li>1 台装有 Ubuntu 的电脑(20.04 或更高版本)</li> +<li>1x Raspberry Pi Model 3B+ 或更高版本,配备 Ubuntu(20.04 或更高版本)而不是 Raspbian OS</li> +</ul> +</li> +<li>1x 蓝牙 LE 加密狗(可以嵌入 PC 内部,就像在树莓派上一样)</li> +<li>1x nRF52840 DK 或 nRF52840 加密狗 - 用于无线电协处理器 (RCP) 设备</li> +<li>1x nRF52840 DK 或 nRF5340 DK - 用于物质附件设备(使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>物质样品</a>之一进行编程))</li> +</ul> +<h3 id="2配置环境">2.配置环境 +</h3><p>要在同一设备上配置和使用线程边界路由器和 Matter 控制器,请完成以下步骤。</p> +<h4 id="step1对样品编程">Step1.对样品编程 +</h4><p>使用可用的 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter.html#matter-samples" target="_blank" rel="noopener" +>Matter 样本</a>之一对 Matter 附件设备的开发套件进行编程。 我们建议使用<a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/matter/light_bulb/README.html#matter-light-bulb-sample" target="_blank" rel="noopener" +>Matter light bulb</a>。</p> +<h4 id="step2thread-border-router配置">Step2.Thread Border Router配置 +</h4><p>在 PC 或树莓派上配置线程边界路由器,具体取决于您使用的硬件。 有关详细步骤,请参阅 nRF Connect SDK 文档中 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/thread/tools.html#ug-thread-tools-tbr" target="_blank" rel="noopener" +>Thread Border Router</a>页面上的使用 Docker 运行 OTBR 部分。</p> +<h4 id="step3chip-tool配置">Step3.Chip Tool配置 +</h4><p>适用于 Linux 或 macOS 的 CHIP Tool 是 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/overview/network_topologies.html#ug-matter-configuring-controller" target="_blank" rel="noopener" +>Matter controller</a> 角色的默认实现,建议用于 nRF Connect 平台。 对于此线程问题,您将在与线程边界路由器相同的设备上配置控制器。</p> +<p>完成以下步骤:</p> +<p>a. 选择以下选项之一:</p> +<ul> +<li>仅适用于 Linux - 使用 <a class="link" href="https://github.com/nrfconnect/sdk-connectedhomeip/releases" target="_blank" rel="noopener" +>Matter nRF Connect 发布</a> GitHub 页面中的预构建工具包。 确保程序包与 nRF Connect SDK 版本兼容。</li> +<li>对于 Linux 和 macOS - 从目录中可用的源文件手动构建它,并使用 Matter 文档中使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>页面中的构建说明。<code>modules/lib/matter/examples/chip-tool</code></li> +</ul> +<p>b. 配置芯片工具控制器。 按照 Matter 文档中的使用 <a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/chip_tool_guide.html" target="_blank" rel="noopener" +>CHIP TOOL</a>用户指南中的步骤完成以下操作:</p> +<ul> +<li>通过完成“构建和运行 CHIP 工具”中列出的步骤来构建和运行 CHIP TOOL。</li> +<li>通过完成“使用 CHIP 工具进行物质设备测试”中列出的步骤来准备测试环境。</li> +</ul> +<h4 id="step4例程测试">Step4.例程测试 +</h4><p>根据您在开发工具包上编程的 Matter 示例,转到对应示例的文档页面并完成“测试”部分中的步骤。</p> +<h2 id="结语">结语 +</h2><p>这部分仅作为开发大纲,后面会出一系列系统教程,以<strong>Matter over Thread::在一台设备上配置边界路由器和控制器</strong>为例。</p> +<hr> +<ul> +<li> +<p><a class="link" href="https://www.youtube.com/watch?v=9Ar13rMxGIk&amp;t=554s" target="_blank" rel="noopener" +>Nordic-Matter 演示教学</a></p> +</li> +<li> +<p><a class="link" href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/matter/getting_started/testing/thread_one_otbr.html" target="_blank" rel="noopener" +>Matter over Thread: Configuring Border Router and controller on one device</a></p> +</li> +</ul> \ No newline at end of file diff --git a/tags/nordic/page/1/index.html b/tags/nordic/page/1/index.html new file mode 100644 index 000000000..8feb90210 --- /dev/null +++ b/tags/nordic/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/nordic/ + \ No newline at end of file diff --git a/tags/nxp/index.html b/tags/nxp/index.html new file mode 100644 index 000000000..cd8e2b811 --- /dev/null +++ b/tags/nxp/index.html @@ -0,0 +1,55 @@ +Tag: NXP - kurisaW +

Tags

4 pages

NXP

\ No newline at end of file diff --git a/tags/nxp/index.xml b/tags/nxp/index.xml new file mode 100644 index 000000000..954c2deba --- /dev/null +++ b/tags/nxp/index.xml @@ -0,0 +1,2127 @@ +NXP on kurisaWhttps://kurisaw.github.io/tags/nxp/Recent content in NXP on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>【NXP】LPC55S69初上手https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/Sun, 05 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%88%9D%E4%B8%8A%E6%89%8B/cover.jpg" alt="Featured image of post 【NXP】LPC55S69初上手" /><h2 id="前言">前言 +</h2><p>前段时间看到恩智浦社区有一个LPC55S69的开发板测评活动,很荣幸能通过报名,第二天也是成功的收到的板子,本次作为开箱测评。</p> +<!-- raw HTML omitted --> +<h2 id="开始测试">开始测试 +</h2><p>首先从RT-Thread仓库的master分支克隆整个仓库,进入目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,首先使用RT-Thread的ENV工具生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">scons</span> <span class="o">--</span><span class="n">target</span><span class="o">=</span><span class="n">mdk5</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051135725.png" +loading="lazy" +alt="image-20230205113527665" +></p> +<p>这里建议大家使用最新版ENV工具。然后双击打开<code>project.uvprojx</code>工程,点击重新编译。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051137011.png" +loading="lazy" +alt="image-20230205113758912" +></p> +<p>但是编译之后发现会有报错,找了很久都没解决,后来经过RTT社区的满老师提示成功解决BUG,下面是解决过程与分析。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140994.png" +loading="lazy" +alt="6d869b905839641fa60aadb8d2a6a9d" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051140331.png" +loading="lazy" +alt="dd1f984d7543997e5fa6fa50aee36c7" +></p> +<h2 id="bug分析与解决">BUG分析与解决 +</h2><p>首先先看一下我的keil版本为V5.25:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051141382.png" +loading="lazy" +alt="4b368869fbf8077591b20eccbd05ef8" +></p> +<p>听满老师讲LPC55S69的工程可能是使用的AC6编译器,但是Keil的V5.25的AC6可能存在问题,所以解决办法就是更新下Keil的版本(建议最新版)</p> +<blockquote> +<p>此处附上Keil<a class="link" href="https://www.keil.com/update/check.asp?P=MDK&amp;V=5.38.0.0&amp;S=" target="_blank" rel="noopener" +>最新版下载官网</a></p> +</blockquote> +<p>下载好最新版本后,前面的步骤重复,然后重新编译下载即可。</p> +<h2 id="项目演示">项目演示 +</h2><p>下面是RT-Thread成功在LPC55S69的示例,可以看到LED灯以500ms进行闪烁:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051354900.gif" +loading="lazy" +alt="video" +></p> +<h2 id="结语">结语 +</h2><p>本博客仅作为开箱测试,后续会继续上传相关测试用例,欢迎讨论交流。</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul>【NXP】LPC55S69开发环境搭建https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/Sat, 04 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/<img src="https://kurisaw.github.io/p/nxplpc55s69%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/cover.jpg" alt="Featured image of post 【NXP】LPC55S69开发环境搭建" /><h2 id="前期准备">前期准备 +</h2><p>资料:</p> +<ul> +<li><a class="link" href="https://www.nxp.com.cn/docs/zh/user-guide/MCUXpresso_IDE_User_Guide.pdf" target="_blank" rel="noopener" +>MCUXpresso_IDE_User_Guide.pdf</a></li> +</ul> +<p>开发环境(官方直链)</p> +<ul> +<li><a class="link" href="https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-peripherals:MCUXpresso-Config-Tools" target="_blank" rel="noopener" +><strong>MCUXpresso Config Tools</strong></a></li> +<li><a class="link" href="https://nxp.flexnetoperations.com/control/frse/download?agree=Accept&amp;element=13944367" target="_blank" rel="noopener" +><strong>MCUXpresso IDE</strong></a></li> +<li><a class="link" href="https://mcuxpresso.nxp.com/zh/welcome" target="_blank" rel="noopener" +><strong>SDK代码包</strong></a></li> +</ul> +<p><code>MCUXpresso Config Tools</code>和<code>MCUXpresso IDE</code>的安装不再赘述,下面是<code>SDK代码包</code>的安装教学</p> +<p>1.选择开发板&ndash;&gt;</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051333457.png" +loading="lazy" +alt="image-20230205133247352" +></p> +<p>2.这里我们选择处理器为LPC55S69(选择自己所需的处理器型号),点击构建MCUXpresso SDK v2.13.0(默认最新即可)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302051334372.png" +loading="lazy" +alt="image-20230205133458266" +></p> +<p>3.根据自己的开发需求进行组件及中间件等,同时选择需要的工具链,这里我们全选,包括工具链和IDE,并点击<code>下载SDK</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302031122007.png" +loading="lazy" +alt="img-202302031122007" +></p> +<p>4.等待构建完成,这里我们选择我们刚刚生成的档案,点击下载软件包</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041022034.png" +loading="lazy" +alt="image-20230204102200685" +></p> +<p>5.直接选择点击下载SDK档案,包括文档。当然这里也提供了单独的示例工程和API参考手册,需要的朋友也可根据需求下载</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041028831.png" +loading="lazy" +></p> +<h2 id="ide配置">IDE配置 +</h2><p>完成IDE软件、配置工具的安装还有SDK代码包的下载后,我们打开<code>MCUXpresso IDE</code>,在主界面的下方栏可以看到有一个<code>Installed SDKs</code>,准备好刚刚下载的SDK代码包,导入其中</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103892.png" +loading="lazy" +alt="image-20230204105301726" +></p> +<p>之后我们就可以使用这个SDK代码包去创建一个新的工程了。</p> +<h2 id="工程导入">工程导入 +</h2><p>这里我们简单做个示范,选择导入示例工程</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041103834.png" +loading="lazy" +alt="image-20230204105601052" +></p> +<p>选择指定的开发板后点击下一步</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041106647.png" +loading="lazy" +alt="image-20230204110547819" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041109611.png" +loading="lazy" +alt="image-20230204110900541" +></p> +<p>在下一步这里,就主要是一些Memory的分散加载问题,还有就是编译器语言的标准问题,一般来讲我们默认不做更改,点击完成即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041114568.png" +loading="lazy" +alt="image-20230204111200845" +></p> +<p>工程的用户代码是存放在source目录下的,我们这时候就可以给开发板上电,然后点击编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041115091.png" +loading="lazy" +alt="image-20230204111519951" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120134.png" +loading="lazy" +alt="image-20230204111803236" +></p> +<p><code>MCUXpresso IDE</code>有两个地方都可以启动调试,选择一个习惯的即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041120777.png" +loading="lazy" +alt="image-20230204112026675" +></p> +<h2 id="配置工具使用">配置工具使用 +</h2><p>和<code>MCUXpresso IDE</code>配套的还有<code>MCUXpresso Config Tools</code>,打开<code>MCUXpresso IDE</code>,找到配置工具按钮打开</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041133492.png" +loading="lazy" +alt="image-20230204113350126" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302041138433.png" +loading="lazy" +alt="image-20230204113817301" +></p> +<h2 id="结语">结语 +</h2><p>到这里就是LPC55S69基本的开发环境的配置及测试了,欢迎大家合作交流!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io/</a></li> +</ul> \ No newline at end of file diff --git a/tags/nxp/page/1/index.html b/tags/nxp/page/1/index.html new file mode 100644 index 000000000..0d0ba88d2 --- /dev/null +++ b/tags/nxp/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/nxp/ + \ No newline at end of file diff --git a/tags/operating-system/index.html b/tags/operating-system/index.html new file mode 100644 index 000000000..2f61eb1f5 --- /dev/null +++ b/tags/operating-system/index.html @@ -0,0 +1,55 @@ +Tag: Operating System - kurisaW +

Tags

3 pages

Operating System

\ No newline at end of file diff --git a/tags/operating-system/index.xml b/tags/operating-system/index.xml new file mode 100644 index 000000000..478a5b912 --- /dev/null +++ b/tags/operating-system/index.xml @@ -0,0 +1,859 @@ +Operating System on kurisaWhttps://kurisaw.github.io/tags/operating-system/Recent content in Operating System on kurisaWHugo -- gohugo.ioenTue, 22 Mar 2022 00:00:00 +0000多线程技术学习(基于Linux)https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Tue, 22 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post 多线程技术学习(基于Linux)" /><h2 id="1linux多线程概念">1.Linux多线程概念 +</h2><blockquote> +<p><strong>(1)线程:指运行中的程序的调度单位。</strong></p> +</blockquote> +<blockquote> +<p><strong>(2)多线程的优点:</strong></p> +</blockquote> +<ul> +<li>运行与一个线程中的多个线程,他们彼此之间使用<strong>相同的地址空间</strong>,<strong>共享大部分数据</strong>,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程见彼此切换所需要的时间也远远小于进程间切换所需要的时间。</li> +<li>进程间方便的通信机制。对不同的进程来说,它们有独立的数据空间,要进行数据的传递智能通过通信的方式</li> +<li>应用程序响应速度提高</li> +<li>使多CPU系统更加高效</li> +<li>改善程序结构</li> +</ul> +<blockquote> +<p><strong>(3)线程的生命周期</strong></p> +</blockquote> +<p>就绪-&gt;运行-&gt;阻塞-&gt;终止</p> +<hr> +<h2 id="2linux线程实现">2.linux线程实现 +</h2><blockquote> +<p><strong>(1)线程创建</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含 +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg) +</code></pre> +</li> +<li> +<p>函数说明: +tidp:线程id +attr:线程属性(通常为空) +start_rtn:线程要执行的函数 <br> +arg: start_rtn的参数</p> +</li> +</ul> +<blockquote> +<p><strong>(2)线程退出</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +void pthread_exit(void * rval_ptr)</li> +<li>功能:终止调用线程Rval_ptr:线程退出返回值的指针。</li> +</ul> +<blockquote> +<p><strong>(3)线程等待</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> int pthread_join(pthread_t tid,void **rval_ptr) +</code></pre> +</li> +<li> +<p>功能:阻塞调用线程,直到指定的线程终止。</p> +</li> +<li> +<p>函数说明: +Tid :等待退出的线程id +Rval_ptr:线程退出的返回值的指针</p> +</li> +</ul> +<blockquote> +<p><strong>(4)线程标识获取</strong></p> +</blockquote> +<ul> +<li>头文件包含: +#include &lt;pthread.h&gt;</li> +<li>定义函数: +pthread_t pthread_self(void)</li> +<li>功能:获取调用线程的 thread identifier</li> +</ul> +<blockquote> +<p><strong>(5)线程清除</strong></p> +</blockquote> +<ul> +<li> +<p>头文件包含: +#include &lt;pthread.h&gt;</p> +</li> +<li> +<p>定义函数:</p> +<pre><code> void pthread_cleanup_push(void (*rtn)(void *),void *arg) +</code></pre> +</li> +<li> +<p>功能:将清除函数压入清除栈</p> +</li> +<li> +<p>函数说明: +Rtn:清除函数 +Arg:清除函数的参数</p> +</li> +</ul> +<hr> +<h2 id="3线程同步的方法">3.线程同步的方法 +</h2><p>进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决线程之间对资源的竞争:</p> +<blockquote> +<p>互斥量(互斥锁)Mutex +信号灯(信号量)Semaphore +条件变量Conditions</p> +</blockquote> +<hr> +<h2 id="4线程的互斥">4.线程的互斥 +</h2><p>线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里。只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。</p> +<blockquote> +<p><strong>(1)创建</strong></p> +</blockquote> +<p>在Linux中, 互斥量使用类型pthread_mutex_t表示。在使用前, 要对它进行初始化:</p> +<ul> +<li>对于静态分配的互斥量, 可以把它设置为默认属性的mutex对象PTHREAD_MUTEX_INITIALIZER</li> +<li>对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy。</li> +</ul> +<blockquote> +<p>函数使用: +头文件: +#include &lt;pthread.h&gt;</p> +</blockquote> +<pre><code>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr) +int pthread_mutex_destroy(pthread_mutex_t *mutex) +</code></pre> +<blockquote> +<p><strong>(2)加锁</strong></p> +</blockquote> +<p>对共享资源的访问, 要使用互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁。</p> +<blockquote> +<p>函数使用:</p> +</blockquote> +<pre><code>int pthread_mutex_lock(pthread_mutex_t *mutex) +int pthread_mutex_trylock(pthread_mutex_t *mutex) +</code></pre> +<p>返回值: 成功则返回0, 出错则返回错误编号. +注意:trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态。</p> +<blockquote> +<p><strong>(3)解锁</strong></p> +</blockquote> +<p>在操作完成后,必须给互斥量解锁,也就是前面所说的释放。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。</p> +<pre><code>int pthread_mutex_unlock(pthread_mutex_t *mutex) +</code></pre> +<hr> +<h2 id="5互斥pk信号量">5.互斥PK信号量 +</h2><blockquote> +<p>Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。 +Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。 +Binary semaphore与Mutex的差异:</p> +<ol> +<li>mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放</li> +<li>初始状态可能不一样:mutex的初始值是1 ,而semaphore的初始值可能是0(或者为1)。</li> +</ol> +</blockquote> +<hr> +<h2 id="6信号量操作代码演示">6.信号量操作(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;semaphore.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">sem_t sem; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sem_wait(&amp;sem); // 接收信号量 +</span></span><span class="line"><span class="cl"> /* +</span></span><span class="line"><span class="cl"> Sem_wait()递减(锁定)sem指向的信号量。如果信号量的值大于0,则继续递减,函数立即返回。 +</span></span><span class="line"><span class="cl"> 如果信号量当前的值为0,那么调用就会阻塞,直到信号量可以递减(即信号量的值高于0),或者信号处理程序中断调用。 +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> //while(strncmp(buf,&#34;end&#34;,3) != 0) +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> sem_init(&amp;sem,0,0); // 在sem指向的地址处初始化未命名的信号量 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(scanf(&#34;%s&#34;,buf)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> sem_post(&amp;sem); //增加(解锁)sem指向的信号量 +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="7互斥操作函数演示">7.互斥操作(函数演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#include&lt;stdio.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;string.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;pthread.h&gt; +</span></span><span class="line"><span class="cl">#include&lt;stdlib.h&gt; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">//子线程处理 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">char buf[200]; +</span></span><span class="line"><span class="cl">pthread_mutex_t mutex; +</span></span><span class="line"><span class="cl">int flag; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void *func(void *arg) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> sleep(1); +</span></span><span class="line"><span class="cl"> while(flag == 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 互斥加锁 +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char.\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 解锁 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_exit(NULL); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int ret = -1; +</span></span><span class="line"><span class="cl"> pthread_t th = -1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> pthread_mutex_init(&amp;mutex,NULL); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> ret = pthread_create(&amp;th,NULL,func,NULL); //pthread_create()函数在调用进程中启动一个新线程,创建成功返回0 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_create error.\n&#34;); +</span></span><span class="line"><span class="cl"> return -1; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;please input string,end with Enter.\n&#34;); +</span></span><span class="line"><span class="cl"> while(1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> pthread_mutex_lock(&amp;mutex);// 对互斥对象加锁锁定 +</span></span><span class="line"><span class="cl"> scanf(&#34;%s&#34;,buf); +</span></span><span class="line"><span class="cl"> pthread_mutex_unlock(&amp;mutex); // 输入后解锁 +</span></span><span class="line"><span class="cl"> if(!strncmp(buf,&#34;end&#34;,3)) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;process end\n&#34;); +</span></span><span class="line"><span class="cl"> flag = 1; +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;input %d char .\n&#34;,strlen(buf)); +</span></span><span class="line"><span class="cl"> memset(buf,0,sizeof(buf)); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> printf(&#34;wait reclaim child thread.\n&#34;); +</span></span><span class="line"><span class="cl"> ret = pthread_join(th,NULL); //pthread_join()函数等待由thread指定的线程结束。如果该线程已经终止,则pthread_join()立即返回。 +</span></span><span class="line"><span class="cl"> if(ret != 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> printf(&#34;pthread_join error.\n&#34;); +</span></span><span class="line"><span class="cl"> exit(-1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> printf(&#34;reclaim child thread successfully.\n&#34;); +</span></span><span class="line"><span class="cl"> pthread_mutex_destroy(&amp;mutex); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><hr> +<h2 id="8条件变量代码演示">8.条件变量(代码演示) +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1">#include&lt;stdio.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;string.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;pthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include&lt;stdlib.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">子线程处理</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pthread_cond_t</span> <span class="n">cond</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">flag</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="o">*</span><span class="k">func</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">flag</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span><span class="o">//</span> <span class="err">互斥加锁</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span><span class="o">//</span> <span class="err">线程同步等待</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> <span class="o">//</span> <span class="err">解锁</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_exit</span><span class="p">(</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="ne">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_t</span> <span class="n">th</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="err">初始化条件变量</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">,</span><span class="k">func</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_create</span><span class="p">()</span><span class="err">函数在调用进程中启动一个新线程</span><span class="p">,</span><span class="err">创建成功返回</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_create error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;please input string,end with Enter.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">scanf</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">发送信号</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="s2">&#34;end&#34;</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;process end</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;input </span><span class="si">%d</span><span class="s2"> char .</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span><span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;wait reclaim child thread.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">th</span><span class="p">,</span><span class="n">NULL</span><span class="p">);</span> <span class="o">//</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">函数等待由</span><span class="n">thread指定的线程结束</span><span class="err">。如果该线程已经终止,则</span><span class="n">pthread_join</span><span class="p">()</span><span class="err">立即返回。</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;pthread_join error.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="s2">&#34;reclaim child thread successfully.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">pthread_cond_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span><span class="o">//</span> <span class="err">条件变量销毁</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>信号量及PV操作详解https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/Thu, 10 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E9%87%8F%E5%8F%8Apv%E6%93%8D%E4%BD%9C%E8%AF%A6%E8%A7%A3/cover.jpg" alt="Featured image of post 信号量及PV操作详解" /><h2 id="信号量">信号量 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->一个特殊变量</li> +<li><!-- raw HTML omitted -->用于进程间传递信息的一个整数值</li> +</ul> +</blockquote> +<p>定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct semaphore +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> int count; +</span></span><span class="line"><span class="cl"> quenue Type quenue; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<ul> +<li><!-- raw HTML omitted -->信号量说明:semaphore s;</li> +<li><!-- raw HTML omitted -->对信号量可以实施的操作:初始化、P和V(P、V分别是荷兰语的test(proberen)和increment(verhogen))</li> +</ul> +</blockquote> +<h2 id="pv操作定义">P、V操作定义 +</h2><p><!-- raw HTML omitted -->P(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.count --; //信号量值减一 +</span></span><span class="line"><span class="cl"> if(s.count&lt;0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 该进程状态置为阻塞态; +</span></span><span class="line"><span class="cl"> 将该进程插入相应的等待队列s.quenue末尾; +</span></span><span class="line"><span class="cl"> 重新调度 +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>down</code>,<code>semwait</code>:也代表P操作</p> +<p><!-- raw HTML omitted -->V(s)<!-- raw HTML omitted --></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> s.ount++; +</span></span><span class="line"><span class="cl"> if(s.count&lt;=0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> 唤醒相应等待队列s.queue中等待的一个进程; +</span></span><span class="line"><span class="cl"> 改变其状态为就绪态,并将其插入就绪队列; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>up</code>,<code>semsignal</code>:也代表V操作</p> +<blockquote> +<p>相关说明</p> +<ul> +<li><!-- raw HTML omitted -->P,V操作为原语操作</li> +<li><!-- raw HTML omitted -->在信号量上定义了三个操作 +<!-- raw HTML omitted -->初始化(非负数)、P操作、V操作<!-- raw HTML omitted --></li> +<li><!-- raw HTML omitted -->最初提出的是二元信号量(解决互斥) +之后,推广到一般信号量(多值)或技术信号量(解决同步)</li> +</ul> +</blockquote> +<h2 id="用pv操作解决进程间互斥问题">用PV操作解决进程间互斥问题 +</h2><blockquote> +<ul> +<li><!-- raw HTML omitted -->分析并发进程的关键活动,划定临界区</li> +<li><!-- raw HTML omitted -->设置信号量mutux,初值为1</li> +<li><!-- raw HTML omitted -->在临界区前实施P(mutux)</li> +<li><!-- raw HTML omitted -->在临界区之后实施V(mutux)</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/9f7d7a26cf6a41048d7205423383fa64.png" +loading="lazy" +alt="图片演示" +></p> +<blockquote> +<p>相关解释:</p> +</blockquote> +<ul> +<li> +<p><code>临界区</code> : 我们把并发进程中与共享变量有关的程序段称为临界区。</p> +</li> +<li> +<p><code>信号量</code> : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。</p> +</li> +<li> +<p><code>进程的互斥</code>:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。</p> +</li> +<li> +<p><code>进程的同步</code>:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。</p> +</li> +<li> +<p><code>pv操作又称wait,signal原语。</code> +主要是操作进程中对进程控制的信息量的加减控制。</p> +</li> +</ul> +<blockquote> +<p><!-- raw HTML omitted --><code>注意:</code>在霍尔管程中,<code>wait操作</code>和<code>signal操作</code>用于被设计为两个可以中断的过程,而非<code>原语。</code> +<!-- raw HTML omitted -->在管程中,引入一种数据结构—条件变量(仅在管程中可以被访问)。 +条件变量的两种操作:</p> +<ul> +<li>wait()操作<!-- raw HTML omitted -->[阻塞调用进程]<!-- raw HTML omitted --></li> +<li>signal()操作<!-- raw HTML omitted -->[释放/唤醒在条件变量上阻塞的进程]<!-- raw HTML omitted --></li> +</ul> +</blockquote> +<ul> +<li>wait用法: +wait(num),num是目标参数,wait的作用是使其(信息量)减一。 +如果信息量&gt;=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 +signal用法: +signal(num),num是目标参数,signal的作用是使其(信息量)加一。 +如果信息量&gt;0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。</li> +</ul> +<blockquote> +<p>本文资源来自<a class="link" href="https://www.coursera.org/learn/os-pku" target="_blank" rel="noopener" +>Operating Systems</a> +参考:<a class="link" href="https://blog.csdn.net/thebestway/article/details/105034840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164992015416780255296134%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&amp;request_id=164992015416780255296134&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-105034840.142%5ev8%5epc_search_result_cache,157%5ev4%5econtrol&amp;utm_term=wait%E5%92%8Csignal%E5%8E%9F%E8%AF%AD&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>操作系统P,V(wait,signal原语)操作讲解</a></p> +</blockquote>进程上下文和线程上下文https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/Tue, 08 Mar 2022 00:00:00 +0000https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/<img src="https://kurisaw.github.io/p/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87/cover.jpg" alt="Featured image of post 进程上下文和线程上下文" /><h2 id="进程">进程 +</h2><p><code>操作系统资源分配的基本单位</code>,也就是指计算机中已执行的程序。</p> +<ul> +<li>在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,<code>进程</code>是程序的基本执行实体;</li> +<li>在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本执行单位,而是<code>线程</code>的容器。</li> +<li>程序本身只是指令、数据及其组织形式的描述,相当于一个名词,<code>进程</code>才是程序(那些指令和数据)的真正<code>执行实例</code>.</li> +</ul> +<h2 id="进程上下文">进程上下文 +</h2><p><code>进程上下文</code>就是表示<code>进程信息</code>的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。</p> +<p>拿<code>Linux进程</code>举例: +&mdash;-进程的运行环境主要包括:</p> +<blockquote> +<p>1.进程空间中的代码和数据、各种数据结构、进程堆栈和共享内存区等。 +2.环境变量:提供进程运行所需的环境信息。 +3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。 +4.进程访问设备或者文件时的权限。 +5.各种硬件寄存器。 +6.地址转换信息。</p> +</blockquote> +<p>由上可知,进程的运行环境是动态变化的,尤其是硬件寄存器的值以及进程控制信息是随着进程的运行而不断变化的。在Linux中把系统提供给进程的的处于动态变化的运行环境总和称为进程上下文。</p> +<h2 id="线程">线程 +</h2><p><code>操作系统能够进行运算调度的最小单位</code>。</p> +<ul> +<li>大部分情况下,它被包含在进程之中,是进程中的实际运作单位。</li> +<li>一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。</li> +<li>线程是独立调度和分派的基本单位。 +线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。</li> +<li>同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。</li> +</ul> +<h2 id="线程上下文">线程上下文 +</h2><p>进程的上下文的多数信息都与地址空间的描述有关。进程的上下文使用很多系统资源,而且会花费一些时间来从一个进程的上下文切换到另一个进程的上下文。<code>同样的,线程也有上下文。</code></p> +<blockquote> +<p>当线程被抢占时,就会发生线程之间的上下文切换。 +如果线程属于相同的进程,它们共享相同的地址空间,因为线程包含在它们所属于的进程的地址空间内。这样,进程需要恢复的多数信息对于线程而言是不需要的。尽管进程和它的线程共享了很多内容,但最为重要的是其地址空间和资源,有些信息对于线程而言是本地且唯一的,而线程的其他方面包含在进程的各个段的内部。</p> +</blockquote> +<p>线程上下文与进程上下文对比</p> +<table> +<thead> +<tr> +<th>上下文内容</th> +<th>进程</th> +<th>线程</th> +</tr> +</thead> +<tbody> +<tr> +<td>指向可执行文件的指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>栈</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>内存(数据段和堆)</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>状态</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>优先级</td> +<td>×</td> +<td>×</td> +</tr> +<tr> +<td>程序IO的状态</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>授予权限</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>调度信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>审计信息</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件描述符</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>文件读/写指针</td> +<td>×</td> +<td></td> +</tr> +<tr> +<td>寄存器组</td> +<td>×</td> +<td>×</td> +</tr> +</tbody> +</table> \ No newline at end of file diff --git a/tags/operating-system/page/1/index.html b/tags/operating-system/page/1/index.html new file mode 100644 index 000000000..2b3021354 --- /dev/null +++ b/tags/operating-system/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/operating-system/ + \ No newline at end of file diff --git a/tags/page/1/index.html b/tags/page/1/index.html new file mode 100644 index 000000000..01802354c --- /dev/null +++ b/tags/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ + \ No newline at end of file diff --git a/tags/page/10/index.html b/tags/page/10/index.html new file mode 100644 index 000000000..0fd35aa82 --- /dev/null +++ b/tags/page/10/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/11/index.html b/tags/page/11/index.html new file mode 100644 index 000000000..0ecc35bcf --- /dev/null +++ b/tags/page/11/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/12/index.html b/tags/page/12/index.html new file mode 100644 index 000000000..2d90edd92 --- /dev/null +++ b/tags/page/12/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/13/index.html b/tags/page/13/index.html new file mode 100644 index 000000000..64897228b --- /dev/null +++ b/tags/page/13/index.html @@ -0,0 +1,60 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/14/index.html b/tags/page/14/index.html new file mode 100644 index 000000000..c1b9fa8d7 --- /dev/null +++ b/tags/page/14/index.html @@ -0,0 +1,59 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/15/index.html b/tags/page/15/index.html new file mode 100644 index 000000000..25e9b1344 --- /dev/null +++ b/tags/page/15/index.html @@ -0,0 +1,58 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/2/index.html b/tags/page/2/index.html new file mode 100644 index 000000000..b361381cc --- /dev/null +++ b/tags/page/2/index.html @@ -0,0 +1,59 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/3/index.html b/tags/page/3/index.html new file mode 100644 index 000000000..fee4cde1c --- /dev/null +++ b/tags/page/3/index.html @@ -0,0 +1,60 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/4/index.html b/tags/page/4/index.html new file mode 100644 index 000000000..ece42fc4a --- /dev/null +++ b/tags/page/4/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/5/index.html b/tags/page/5/index.html new file mode 100644 index 000000000..e5c2ce9cc --- /dev/null +++ b/tags/page/5/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/6/index.html b/tags/page/6/index.html new file mode 100644 index 000000000..ca378fb72 --- /dev/null +++ b/tags/page/6/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/7/index.html b/tags/page/7/index.html new file mode 100644 index 000000000..b6c35f479 --- /dev/null +++ b/tags/page/7/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/8/index.html b/tags/page/8/index.html new file mode 100644 index 000000000..f214a9c47 --- /dev/null +++ b/tags/page/8/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/page/9/index.html b/tags/page/9/index.html new file mode 100644 index 000000000..916bb7bbb --- /dev/null +++ b/tags/page/9/index.html @@ -0,0 +1,61 @@ +Tags +

Section

73 pages

Tags

\ No newline at end of file diff --git a/tags/platform/index.html b/tags/platform/index.html new file mode 100644 index 000000000..fca0e4543 --- /dev/null +++ b/tags/platform/index.html @@ -0,0 +1,55 @@ +Tag: Platform - kurisaW +

Tags

1 page

Platform

\ No newline at end of file diff --git a/tags/platform/index.xml b/tags/platform/index.xml new file mode 100644 index 000000000..13281e37d --- /dev/null +++ b/tags/platform/index.xml @@ -0,0 +1,698 @@ +Platform on kurisaWhttps://kurisaw.github.io/tags/platform/Recent content in Platform on kurisaWHugo -- gohugo.ioenSun, 20 Aug 2023 00:00:00 +0000【Matter】CHIP设备层设计笔记https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/Sun, 20 Aug 2023 00:00:00 +0000https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/<img src="https://kurisaw.github.io/p/matterchip%E8%AE%BE%E5%A4%87%E5%B1%82%E8%AE%BE%E8%AE%A1%E7%AC%94%E8%AE%B0/cover.jpg" alt="Featured image of post 【Matter】CHIP设备层设计笔记" /><h1 id="chip设备层设计笔记">CHIP设备层设计笔记 +</h1><p>本文档包含与 CHIP 设备层 ( <code>src/platform</code>) 内部设计相关的概述、注释和其他信息材料。它旨在作为对实现者有价值的主题的托管文档的地方,但由于大小或范围的原因,它自然不适合代码中的注释。</p> +<p>这是一个动态文档,具有非正式的结构,随代码一起发展。我们鼓励开发人员添加他们认为对其他工程师有用的东西。</p> +<p>本文档包含以下部分:</p> +<ul> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Device-Layer-Adaptation-Patterns" target="_blank" rel="noopener" +>设备层适配模式</a></li> +</ul> +<hr> +<h3 id="设备层适配模式">设备层适配模式 +</h3><p>设备层使用各种设计模式,使代码更容易适应不同的平台和操作环境。</p> +<p>CHIP 设备层旨在跨各种平台和操作环境工作。这些环境可能因系统类型、操作系统、网络堆栈和/或线程模型而异。设备层的目标之一是使 CHIP 应用程序堆栈能够轻松适应新环境。在新平台与现有改编基本相似的情况下,这是特别理想的。</p> +<p>作为其设计的一部分,CHIP 设备层支持代码重用模式,努力减少对预处理器条件(例如#ifdef)的需求。虽然没有完全消除#ifdef,但该设计允许将行为中的主要差异表示为不同的代码库(通常是单独的 C++ 类),然后通过组合将它们组合在一起以实现特定的适应。</p> +<p>为了提高应用程序的可移植性,CHIP 设备层采用静态多态性模式将其应用程序可见的 API 与底层特定于平台的实现隔离开来。设备层本身使用类似的接口模式来提供组件之间的划分。</p> +<p>尽可能通过使用零成本抽象模式(代码大小和执行开销方面的零成本)来实现上述目标。我们努力使模式易于使用,没有太多的概念负担或繁琐的语法。</p> +<p>以下各节描述了用于实现这些目标的一些模式。</p> +<ol> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Interface-and-Implementation-Classes" target="_blank" rel="noopener" +>接口和实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Method-Forwarding" target="_blank" rel="noopener" +>方法转发</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Target-Platform-Selection" target="_blank" rel="noopener" +>目标平台选择</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Generic-Implementation-Classes" target="_blank" rel="noopener" +>通用实现类</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Overriding-Generic-Behaviors" target="_blank" rel="noopener" +>覆盖通用行为</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Multiple-Inheritance-and-Subclassing-of-Generic-Implementations" target="_blank" rel="noopener" +>通用实现的多重继承和子类化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#Static-Virtualization-of-Generic-Implementation-Behavior" target="_blank" rel="noopener" +>通用实现行为的静态虚拟化</a></li> +<li><a class="link" href="https://github.com/project-chip/connectedhomeip/tree/master/src/platform#-ipp-files-and-explicit-template-instantiation" target="_blank" rel="noopener" +>.cpp 文件和显式模板实例化</a></li> +</ol> +<hr> +<h3 id="接口和实现类">接口和实现类 +</h3><p>CHIP设备层使用双类模式将组件对象的抽象特征(通常是其外部可见的方法)与特定平台上这些特征的具体实现分开。遵循这种模式,设备层中的每个主要组件都体现在(至少)两个 C++ 类中:一个抽象接口类和一个实现类。</p> +<p>外部可见的<em><strong>抽象接口类</strong></em>定义了一组通用方法(以及可能的其他成员),这些方法对组件用户普遍可用,但独立于底层实现。接口类本身不包含任何功能,而是使用零成本抽象技术将所有方法调用转发到关联的实现类。接口类用于形式化组件的功能接口,并提供托管与实现无关的 API 文档的位置。</p> +<p>实现<em><strong>类</strong></em>提供了接口类公开的逻辑功能的具体的、特定于平台的实现。这一功能可以由类本身直接提供(即在其方法内),或者通过委托给一个或多个辅助类来提供。</p> +<p>设备层的每个主要应用程序可见组件都存在成对的抽象接口类和实现类。此外,在设备层中定义了类似的类对,以帮助组件之间的隔离。</p> +<p>抽象接口类根据它们提供的功能来命名,例如ConfigurationManager、ConnectivityManager 等。实现类采用其接口类的名称并附加后缀<code>Impl</code>。在所有情况下,实现类都需要从其接口类公开继承。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for a specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="方法转发">方法转发 +</h3><p>接口类通过称为转发方法的短内联函数将***方法调用转发***到其实现类。<code>this</code>这些方法通过向下转换对象的指针并调用实现类上类似命名的方法来转发来自应用程序的调用。此模式类似于 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪的重复模板模式</a> ,不同之处在于基类和子类之间的关系是固定的,而不是表示为模板参数。接口内使用了类型别名named,<code>ImplClass</code>使转发方法定义更加简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* forward method call... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>该模式的一个便利功能是它允许转发静态方法以及实例方法。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>作为转发方法目标的实现类上的方法称为*<strong>实现方法*</strong>。每一种转发方法都必须有相应的实现方法。</p> +<p>前导下划线(_)用于区分实现方法与其转发方法。这种安排有助于强调两者之间的区别,并确保在实现者忽略提供实现方法时生成编译错误。</p> +<p>实现方法并不意味着直接调用。为了阻止这种类型的使用,实现类将其实现方法声明为私有,然后使用友元声明为接口类提供(唯一)调用这些方法作为转发的一部分的权利。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final : public ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Let the forwarding methods on ConfigurationManager call implementation +</span></span><span class="line"><span class="cl"> methods on this class. */ +</span></span><span class="line"><span class="cl"> friend ConfigurationManager; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">private: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR _Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding implementation method... */ +</span></span><span class="line"><span class="cl"> return static_cast&lt;ImplClass*&gt;(this)-&gt;_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl">} +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">inline CHIP_ERROR ConfigurationManager::Init() +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* Forward calls to corresponding static implementation method... */ +</span></span><span class="line"><span class="cl"> return ImplClass::_Init(); +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="目标平台选择">目标平台选择 +</h3><p>实现类提供了在特定平台上使用的设备层组件的具体实现。同一组件的设备层源代码树中可能存在多个实现类。每个类都具有相同的名称,但它们的代码对于相关平台来说是唯一的。在编译时选择包含哪个实现类是通过计算的 #include 指令完成的,其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of ConfigurationManager.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">#define CONFIGURATIONMANAGERIMPL_HEADER \ +</span></span><span class="line"><span class="cl"> &lt;platform/CHIP_DEVICE_LAYER_TARGET/ConfigurationManagerImpl.h&gt; +</span></span><span class="line"><span class="cl">#include CONFIGURATIONMANAGERIMPL_HEADER +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">... +</span></span></code></pre></td></tr></table> +</div> +</div><p>该指令出现在定义组件接口类的头文件中。C++ 预处理器自动扩展 #include 行以根据所选平台选择适当的实现标头。这样,包含组件接口头文件的源文件自然也可以获得正确的实现头文件。</p> +<p>每个受支持平台的实现头文件都排列在以其目标平台命名的子目录中(例如<code>ESP32</code>)。所有此类文件都具有相同的文件名(例如<code>ConfigurationManagerImpl.h</code>),并且每个文件都包含类似名称的类的定义(<code>ConfigurationManagerImpl</code>)。</p> +<p>特定于平台的源文件放置在紧邻设备层根源目录下面的子目录中(例如 <code>src/adaptations/device-layer/ESP32</code>)。与特定于平台的头目录一样,这些子目录以目标平台命名。</p> +<p>设备层目标平台的选择是在项目配置时使用配置脚本选项指定的 <code>--device-layer=&lt;target-platform&gt;</code>。传递 &ndash;device-layer 选项会导致一对预处理器符号的定义,其中目标平台的名称已合并到定义中。例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET ESP32 +</span></span><span class="line"><span class="cl">#define CHIP_DEVICE_LAYER_TARGET_ESP32 1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>&ndash;device-layer 配置选项还选择要包含在生成的库文件中的适当的特定于平台的源文件集。这是通过设备层 Makefile.am 中的逻辑完成的。</p> +<h3 id="通用实现类">通用实现类 +</h3><p>通常可以在一系列平台上共享实现代码。在某些情况下,所有目标的相关代码基本上都是相同的,每种情况下只需要进行少量的定制。在其他情况下,实现的通用性扩展到共享特定架构功能的平台子集,例如通用操作系统(Linux、FreeRTOS)或网络堆栈(套接字、LwIP)。</p> +<p>为了适应这一点,CHIP 设备层鼓励采用一种将通用功能分解为***通用实现基类的***模式。然后,这些基类用于组成(通过继承)构成组件基础的具体实现类。</p> +<p>通用实现基类被实现为遵循 C++ <a class="link" href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="_blank" rel="noopener" +>奇怪重复模板模式的</a>C++ 类模板。希望合并常见行为的实现类从模板的实例继承,将实现类本身作为模板的参数传递。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Implementation provided by +</span></span><span class="line"><span class="cl"> generic base class. */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在许多情况下,通用实现基类本身将直接提供满足组件接口所需的部分或全部实现方法。C++ 方法解析的规则是对接口类上的转发方法的调用直接映射到基类方法。在这种情况下,派生实现类根本不需要声明目标方法的版本,并且方法调用在编译时静态转发,没有任何开销。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Interface class for ConfigurationManager component +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManager +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using ImplClass = ConfigurationManagerImpl; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">public: +</span></span><span class="line"><span class="cl"> CHIP_ERROR GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> static CHIP_ERROR Init(); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing ConfigurationManager components +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); /* &lt;-- Invoked when GetDeviceId() called. */ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="覆盖通用行为">覆盖通用行为 +</h3><p>如果需要,具体实现类可以自由地覆盖通用基类提供的实现方法。这是通过在实现类上定义该方法的特定于平台的版本来完成的。C++ 的规则导致优先于泛型方法调用实现类上的方法。</p> +<p>新方法可以完全取代通用方法的行为,或者可以通过在其自己的实现过程中调用通用方法来增强其行为。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">CHIP_ERROR ConfigurationManagerImpl::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> using GenericImpl = GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Call the generic implementation to get the device id. */ +</span></span><span class="line"><span class="cl"> uint64_t deviceId = GenericImpl::_GetDeviceId(deviceId); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* Special case the situation where the device id is not known. */ +</span></span><span class="line"><span class="cl"> if (deviceId == kNodeIdNotSpecified) { +</span></span><span class="line"><span class="cl"> deviceId = PLATFORM_DEFAULT_DEVICE_ID; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return deviceId; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现的多重继承和子类化">通用实现的多重继承和子类化 +</h3><p>具体实现类可以自由地从多个通用基类继承。当组件的整体功能可以自然地分割成独立的片(例如支持 WiFi 的方法和支持 Thread 的方法)时,此模式特别有用。然后,每个这样的切片都可以通过一个不同的基类来实现,该基类最终在最终实现中与其他基类组合在一起。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Concrete implementation of ConfigurationManager component for specific platform +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">class ConfigurationManagerImpl final +</span></span><span class="line"><span class="cl"> : public ConfigurationManager, +</span></span><span class="line"><span class="cl"> public GenericWiFiConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt;, /* &lt;-- WiFi features */ +</span></span><span class="line"><span class="cl"> public GenericThreadConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; /* &lt;-- Thread features */ +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><p>通用实现基类还可以从其他通用基类继承。这对于“专门化”特定用例子范围(例如,特定操作系统类型)的通用实现非常有用。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on all platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/** Generic base class for use in implementing PlatformManager features +</span></span><span class="line"><span class="cl"> * on FreeRTOS platforms. +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericPlatformManagerImpl_FreeRTOS +</span></span><span class="line"><span class="cl"> : public GenericPlatformManagerImpl&lt;ImplClass&gt; +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="通用实现行为的静态虚拟化">通用实现行为的静态虚拟化 +</h3><p>在创建通用实现基类时,如果操作可能或必须以特定于平台的方式实现,则鼓励开发人员使用静态虚拟化模式将操作委托给具体实现类。</p> +<p>例如,考虑 ConfigurationManager 组件的通用实现,其中值访问器方法通过<code>GetDeviceId()</code>从底层键值存储中检索值来进行操作。键值存储的实现方式的细节可能会因平台而异。为了实现这一点,通用实现类被构造为将检索键值的操作委托给具体实现类上的方法。</p> +<p><code>this</code>遵循奇怪的重复模板模式,通过将指针强制转换为实现类并调用具有适当签名的方法来完成委托。名为 的内联辅助函数<code>Impl()</code>有助于使代码简洁。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericConfigurationManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ConfigurationManagerImpl</span> <span class="n">final</span> +</span></span><span class="line"><span class="cl"> <span class="p">:</span> <span class="n">public</span> <span class="n">ConfigurationManager</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">public</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">friend</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">CHIP_ERROR</span> <span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_GetDeviceId</span><span class="p">(</span><span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">deviceId</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">delegate</span> <span class="n">to</span> <span class="n">the</span> <span class="n">implementation</span> <span class="k">class</span> <span class="n">to</span> <span class="n">read</span> <span class="n">the</span> <span class="s1">&#39;device-id&#39;</span> <span class="n">config</span> <span class="n">value</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="err">“</span><span class="n">device</span><span class="o">-</span><span class="n">id</span><span class="err">”</span><span class="p">,</span> <span class="n">deviceId</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">CHIP_ERROR</span> <span class="n">ConfigurationManagerImpl</span><span class="p">::</span><span class="n">ReadConfigValue</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="n">uint64_t</span> <span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">read</span> <span class="n">value</span> <span class="n">from</span> <span class="n">platform</span><span class="o">-</span><span class="n">specific</span> <span class="n">key</span><span class="o">-</span><span class="n">value</span> <span class="n">store</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的示例中,委托方法在概念上是“纯虚拟”的,因为具体实现类必须提供该方法的版本,否则编译将失败。在其他情况下,可以使用类似的模式来允许实现根据需要覆盖基类提供的默认行为。</p> +<p>同样,委托是通过转换<code>this</code>指针并调用适当的方法来发生的。然而,在这种情况下,通用基类提供了目标方法的默认实现,除非子类重写它,否则将使用该目标方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">GenericPlatformManagerImpl</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">protected</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="n">private</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ImplClass</span> <span class="o">*</span> <span class="n">Impl</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">static_cast</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">this</span><span class="p">);</span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">_DispatchEvent</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">Delegate</span> <span class="n">work</span> <span class="n">to</span> <span class="n">method</span> <span class="n">that</span> <span class="n">can</span> <span class="n">be</span> <span class="n">overridden</span> <span class="n">by</span> <span class="n">implementation</span> <span class="k">class</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">Impl</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="n">event</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="n">ImplClass</span><span class="o">&gt;</span> +</span></span><span class="line"><span class="cl"><span class="n">void</span> <span class="n">GenericPlatformManagerImpl</span><span class="o">&lt;</span><span class="n">ImplClass</span><span class="o">&gt;</span><span class="p">::</span><span class="n">DispatchEventToApplication</span><span class="p">(</span><span class="k">const</span> <span class="n">CHIPDeviceEvent</span> <span class="o">*</span> <span class="n">event</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="n">provide</span> <span class="n">default</span> <span class="n">implementation</span> <span class="n">of</span> <span class="n">DispatchEventToApplication</span><span class="p">()</span> <span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="cpp-文件和显式模板实例化">.cpp 文件和显式模板实例化 +</h3><p>C++ 模板的规则要求编译器在实例化时“查看”类模板的完整定义。(在此上下文中的实例化意味着编译器被迫根据模板提供的配方生成实际的类)。通常,这需要将类模板的整个定义(包括其所有方法)放入头文件中,然后必须在实例化之前将其包含在内。</p> +<p>为了将类模板的定义与其成员的定义分开,CHIP 设备层将所有非内联模板成员定义放入单独的文件中。该文件与模板头文件具有相同的基本名称,但带有后缀<code>.cpp</code>。这种模式减少了头文件中的混乱,并且可以仅在需要时才包含非内联成员定义(更多内容见下文)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.h */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">class GenericConfigurationManagerImpl +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">protected: +</span></span><span class="line"><span class="cl"> CHIP_ERROR _GetDeviceId(uint64_t &amp; deviceId); +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* contents of GenericConfigurationManagerImpl.cpp */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">template&lt;class ImplClass&gt; +</span></span><span class="line"><span class="cl">CHIP_ERROR GenericConfigurationManagerImpl&lt;ImplClass&gt;::_GetDeviceId(uint64_t &amp; deviceId) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> ... +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p>通常情况下,C++ 编译器被迫多次实例化类模板,为其编译的每个 .cpp 文件实例化一次。这会显着增加编译过程的开销。<a class="link" href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation" target="_blank" rel="noopener" +>为了避免这种情况,设备层使用显式模板实例化</a>的 C++11 技术 来指示编译器仅实例化模板一次。这是通过两个步骤完成的:首先,所有使用类模板的头文件<code>extern template class</code>在使用模板类之前都包含一个声明。这告诉编译器<em>不要</em>在该上下文中实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.h */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Instruct the compiler to instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; +</span></span></span><span class="line"><span class="cl"><span class="c1">// class only when explicitly asked to do so. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">extern</span> <span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后,在相应的 .cpp 文件中,包含模板的 .cpp 文件,并<code>template class</code>使用定义来强制显式实例化模板。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* contents of ConfigurationManagerImpl.cpp */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;CHIP/DeviceLayer/internal/GenericConfigurationManagerImpl.cpp&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// Fully instantiate the GenericConfigurationManagerImpl&lt;ConfigurationManagerImpl&gt; class. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">template</span> <span class="n">class</span> <span class="n">GenericConfigurationManagerImpl</span><span class="o">&lt;</span><span class="n">ConfigurationManagerImpl</span><span class="o">&gt;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">...</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>结果是,在编译引用的 .cpp 文件期间,模板的非内联成员仅被解析和实例化一次,从而避免了其他上下文中的冗余处理。</p> \ No newline at end of file diff --git a/tags/platform/page/1/index.html b/tags/platform/page/1/index.html new file mode 100644 index 000000000..bf6e94ef2 --- /dev/null +++ b/tags/platform/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/platform/ + \ No newline at end of file diff --git a/tags/rdc/index.html b/tags/rdc/index.html new file mode 100644 index 000000000..622e0f663 --- /dev/null +++ b/tags/rdc/index.html @@ -0,0 +1,55 @@ +Tag: RDC - kurisaW +

Tags

1 page

RDC

\ No newline at end of file diff --git a/tags/rdc/index.xml b/tags/rdc/index.xml new file mode 100644 index 000000000..d3b9f258b --- /dev/null +++ b/tags/rdc/index.xml @@ -0,0 +1,190 @@ +RDC on kurisaWhttps://kurisaw.github.io/tags/rdc/Recent content in RDC on kurisaWHugo -- gohugo.ioenThu, 19 Jan 2023 00:00:00 +0000RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p> \ No newline at end of file diff --git a/tags/rdc/page/1/index.html b/tags/rdc/page/1/index.html new file mode 100644 index 000000000..cc2728629 --- /dev/null +++ b/tags/rdc/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/rdc/ + \ No newline at end of file diff --git a/tags/risc-v/index.html b/tags/risc-v/index.html new file mode 100644 index 000000000..69e3fd73b --- /dev/null +++ b/tags/risc-v/index.html @@ -0,0 +1,55 @@ +Tag: Risc-V - kurisaW +

Tags

1 page

Risc-V

\ No newline at end of file diff --git a/tags/risc-v/index.xml b/tags/risc-v/index.xml new file mode 100644 index 000000000..dfc50ca74 --- /dev/null +++ b/tags/risc-v/index.xml @@ -0,0 +1,190 @@ +Risc-V on kurisaWhttps://kurisaw.github.io/tags/risc-v/Recent content in Risc-V on kurisaWHugo -- gohugo.ioenThu, 19 Jan 2023 00:00:00 +0000RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p> \ No newline at end of file diff --git a/tags/risc-v/page/1/index.html b/tags/risc-v/page/1/index.html new file mode 100644 index 000000000..97bbcc31e --- /dev/null +++ b/tags/risc-v/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/risc-v/ + \ No newline at end of file diff --git a/tags/ros2/index.html b/tags/ros2/index.html new file mode 100644 index 000000000..fcd1c0f71 --- /dev/null +++ b/tags/ros2/index.html @@ -0,0 +1,55 @@ +Tag: ROS2 - kurisaW +

Tags

1 page

ROS2

\ No newline at end of file diff --git a/tags/ros2/index.xml b/tags/ros2/index.xml new file mode 100644 index 000000000..5ea25b8b4 --- /dev/null +++ b/tags/ros2/index.xml @@ -0,0 +1,472 @@ +ROS2 on kurisaWhttps://kurisaw.github.io/tags/ros2/Recent content in ROS2 on kurisaWHugo -- gohugo.ioenThu, 26 Oct 2023 00:00:00 +0000【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul> \ No newline at end of file diff --git a/tags/ros2/page/1/index.html b/tags/ros2/page/1/index.html new file mode 100644 index 000000000..db6da2de9 --- /dev/null +++ b/tags/ros2/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ros2/ + \ No newline at end of file diff --git a/tags/rt-smart/index.html b/tags/rt-smart/index.html new file mode 100644 index 000000000..ff8429e42 --- /dev/null +++ b/tags/rt-smart/index.html @@ -0,0 +1,55 @@ +Tag: RT-Smart - kurisaW +

Tags

1 page

RT-Smart

\ No newline at end of file diff --git a/tags/rt-smart/index.xml b/tags/rt-smart/index.xml new file mode 100644 index 000000000..4ffd2edd6 --- /dev/null +++ b/tags/rt-smart/index.xml @@ -0,0 +1,190 @@ +RT-Smart on kurisaWhttps://kurisaw.github.io/tags/rt-smart/Recent content in RT-Smart on kurisaWHugo -- gohugo.ioenThu, 19 Jan 2023 00:00:00 +0000RDC 2022纪念版开发板-D1S在RT-Smart运行https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/Thu, 19 Jan 2023 00:00:00 +0000https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/<img src="https://kurisaw.github.io/p/rdc-2022%E7%BA%AA%E5%BF%B5%E7%89%88%E5%BC%80%E5%8F%91%E6%9D%BF-d1s%E5%9C%A8rt-smart%E8%BF%90%E8%A1%8C/cover.jpg" alt="Featured image of post RDC 2022纪念版开发板-D1S在RT-Smart运行" /><h2 id="开发环境">开发环境 +</h2><p>软件</p> +<ul> +<li>ubuntu20.04</li> +<li>VMware Workstation</li> +</ul> +<p>硬件</p> +<ul> +<li>RDC2022纪念版开发板</li> +<li>全志D1s芯片</li> +</ul> +<h2 id="材料下载">材料下载 +</h2><p>首先打开虚拟机,创建一个目录存放本次测试的代码,然后克隆RT-Smart用户态代码。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">userapps</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191107894.png" +loading="lazy" +alt="image-20230119110742488" +></p> +<p>在<code>userapps</code>目录下克隆RT-Thread仓库代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nf">git clone https</span><span class="o">:</span>//<span class="n">github</span>.<span class="n">com</span>/<span class="n">RT</span>-<span class="n">Thread</span>/<span class="n">rt</span>-<span class="n">thread</span>.<span class="n">git</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191109402.png" +loading="lazy" +alt="image-20230119110934253" +></p> +<h2 id="riscv工具链配置">Riscv工具链配置 +</h2><p>进入<code>userapps/tools</code>,运行 get_toolchain.py 的脚本,会下载对应的工具链并展开到<code> userapps\tools\gun_gcc</code> 目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">python3</span> <span class="err">get_toolchain.py</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191118227.png" +loading="lazy" +alt="image-20230119111856993" +></p> +<p>返回上一级,刷新工具链环境,同时记住这里的<code>EXEC_PATH</code>工具链路径,后面需要修改为此路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">cd</span> <span class="err">..</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">smart-env.sh</span> <span class="err">riscv64</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191115786.png" +loading="lazy" +alt="image-20230119111552268" +></p> +<h2 id="内核环境编译">内核环境编译 +</h2><h4 id="scons安装">scons安装 +</h4><p>环境编译会用到<code>scons</code>,所以我们先下载scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">apt</span> <span class="err">install</span> <span class="err">scons</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>查看scons版本信息可判断是否安装成功</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191121945.png" +loading="lazy" +alt="image-20230119112101897" +></p> +<h4 id="env工具安装">env工具安装 +</h4><p>依次执行以下程序:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">scons</span> <span class="err">--menuconfig</span> +</span></span><span class="line"><span class="cl"><span class="err">source</span> <span class="err">~/.env/env.sh</span> +</span></span><span class="line"><span class="cl"><span class="err">pkgs</span> <span class="err">--update</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="内核编译">内核编译 +</h4><p>使用 scons 命令进行编译,编译成功后会在 <code>userapps/rt-thread/bsp/allwinner/d1s</code> 目录下生成 <code>sd.bin</code>,这个文件就是我们需要烧录到开发板中的文件,它包括了 <code>uboot.dtb,opensbi,rtthread.bin</code>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时直接编译会报错,因为工具链路径还没有修改</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191129532.png" +loading="lazy" +alt="image-20230119112916923" +></p> +<p>我们复制上面的工具链路径,vi命令修改rtconfig.py,这里的路径依据你自己的工具链路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191132933.png" +loading="lazy" +alt="image-20230119113207832" +></p> +<p>再次执行scons命令编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191133159.png" +loading="lazy" +alt="image-20230119113353060" +></p> +<h2 id="程序烧录">程序烧录 +</h2><p>我这里采用的是从TF卡作为启动方式。</p> +<p>1、首先准备一张容量在128G的空白TF卡</p> +<p>2、格式化TF卡,并使用ubuntu的gparted工具重新分区</p> +<p>如果没有下载该工具可使用下面的命令进行下载:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">gparted</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>启动该工具</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo gparted +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我使用的是一张64G的TF卡,扇区大小为512字节,同时我们需要预留8M的前空间,并且分区的文件系统格式为fat32</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191140208.png" +loading="lazy" +alt="image-20230119114019113" +></p> +<p>3、接下来进行程序的烧录</p> +<p>首先进入<code>userapps/rt-thread/bsp/allwinner/d1s/tools</code>,执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>boot0_sdcard_sun20iw1p1_d1s.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">8</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191144935.png" +loading="lazy" +alt="image-20230119114457823" +></p> +<p>返回上一级,再次执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">sudo</span> <span class="err">dd</span> <span class="nv">if</span><span class="o">=</span>sd.bin <span class="nv">of</span><span class="o">=</span>/dev/sdb <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">seek</span><span class="o">=</span><span class="m">56</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191146686.png" +loading="lazy" +alt="image-20230119114605503" +></p> +<p>到此烧录工作已完成。</p> +<h2 id="启动rt-smart">启动RT-Smart +</h2><p>我们将刚刚烧录好程序的TF卡直接插入到开发板卡槽,并连接开发板UART端口进行串口查看验证。</p> +<p>此处注意串口波特率为<code>500000</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191153203.png" +loading="lazy" +alt="image-20230119115334091" +></p> +<p>简单测试下MSH命令:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301191159278.png" +loading="lazy" +alt="image-20230119115950076" +></p> +<p>到此就测试结束啦,欢迎大家讨论交流。</p> \ No newline at end of file diff --git a/tags/rt-smart/page/1/index.html b/tags/rt-smart/page/1/index.html new file mode 100644 index 000000000..14af14544 --- /dev/null +++ b/tags/rt-smart/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/rt-smart/ + \ No newline at end of file diff --git a/tags/rt-thread/index.html b/tags/rt-thread/index.html new file mode 100644 index 000000000..48fde9e2f --- /dev/null +++ b/tags/rt-thread/index.html @@ -0,0 +1,57 @@ +Tag: RT-Thread - kurisaW +

Tags

15 pages

RT-Thread

\ No newline at end of file diff --git a/tags/rt-thread/index.xml b/tags/rt-thread/index.xml new file mode 100644 index 000000000..725db1769 --- /dev/null +++ b/tags/rt-thread/index.xml @@ -0,0 +1,8386 @@ +RT-Thread on kurisaWhttps://kurisaw.github.io/tags/rt-thread/Recent content in RT-Thread on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduinohttps://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover.jpg" alt="Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino" /><h1 id="瑞萨hmi-board使用vscode开发rtduino结合ssd1306-oled">瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) +</h1><hr> +<h2 id="1准备工作">1.准备工作 +</h2><p>软件环境:</p> +<ul> +<li><a class="link" href="https://github.com/RT-Thread/rt-thread" target="_blank" rel="noopener" +> RT-Thread 主仓代码(需下载至本地)</a></li> +<li>vscode</li> +<li>rt-thread env</li> +</ul> +<p>硬件环境:</p> +<ul> +<li>RA6M3-HMI-Board 开发板</li> +<li>0.96寸 ssd1306 oled 显示屏</li> +</ul> +<h2 id="2工程配置">2.工程配置 +</h2><p>首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要我们提前安装好 ENV 环境,具体细节请参考 <a class="link" href="https://docs.rtduino.com/#/zh/beginner/env?id=env%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba" target="_blank" rel="noopener" +>Env编译环境搭建</a> 。</p> +<p>鼠标右键打开 ENV 工具后,使用 <strong>menuconfig</strong> 命令打开可视化菜单,勾选上 <strong>RTduino</strong> 的使能项,保存并退出</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251.png" +width="1086" +height="392" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123170636251" +class="gallery-image" +data-flex-grow="277" +data-flex-basis="664px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">RT-Thread Configuration +</span></span><span class="line"><span class="cl"> → Hardware Drivers Config +</span></span><span class="line"><span class="cl"> → Onboard Peripheral Drivers +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Compatible with Arduino Ecosystem <span class="o">(</span>RTduino<span class="o">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123171151275" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623.png" +width="1682" +height="768" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173108623" +class="gallery-image" +data-flex-grow="219" +data-flex-basis="525px" +></p> +<h2 id="3开始编译">3.开始编译 +</h2><p>打开 ENV ,同时执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons -j16 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173509831" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>在工程编译完成后会生成一个 <code>.elf</code>后缀的可执行文件,到这里工程的编译就顺利结束了。</p> +<h2 id="4vscode调试配置">4.vscode调试配置 +</h2><p>首先我们需要在 vscode 中安装 <code>Cortex-Debug</code> 插件,打开 vscode 扩展,搜索 <code>Cortex-Debug</code>并安装扩展:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123175244073" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接下来就是安装 <code>pyocd</code> 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 <code>create a launch.json file</code>:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889.png" +width="1385" +height="462" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123180230889" +class="gallery-image" +data-flex-grow="299" +data-flex-basis="719px" +></p> +<p>之后 vscode 会创建一份 <code>launch.json</code> 文件,我们需要替换文件内容为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// Use IntelliSense to learn about possible attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Hover to view descriptions of existing attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.2.0&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;configurations&#34;</span><span class="p">:</span> <span class="p">[</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;HMI-Board&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;cwd&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceFolder}&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;executable&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;request&#34;</span><span class="p">:</span> <span class="s2">&#34;launch&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;cortex-debug&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;runToEntryPoint&#34;</span><span class="p">:</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;targetId&#34;</span><span class="p">:</span> <span class="s2">&#34;R7FA6M3AH&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;servertype&#34;</span><span class="p">:</span> <span class="s2">&#34;pyocd&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;serverpath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/compile/sdk-debugger-pyocd/pyocd.bat&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;armToolchainPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;gdbPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<code>launch.json</code>文件中的部分参数需要根据具体位置配置</p> +<ul> +<li><code>serverpath</code>:这部分路径在前面所安装的 <code>sdk-debugger-pyocd</code>位置</li> +<li><code>armToolchainPath</code>:gcc 工具链,找不到位置的可以<a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>点击此处下载</a></li> +<li><code>gdbPath</code></li> +</ul> +<p>在完成上述配置后就可以点击 <code>F5</code> 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123183906784" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932.png" +width="815" +height="536" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184032932" +class="gallery-image" +data-flex-grow="152" +data-flex-basis="364px" +></p> +<p>到这里 RTduino 就已经成功运行在 RT-Thread 啦!</p> +<h2 id="5demo使用-rtduino-驱动-096寸-ssd1306-oled">5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled +</h2><p>在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过<code>RTduino</code>,并在<code>RT-Thread</code>中使用 <code>Arduino</code> 源码驱动一个 oled 屏幕。</p> +<p>我们接着回到 ENV 中,使用 <code>menuconfig</code>命令打开菜单,同时使用 <code>shift + /</code>打开搜索界面,并且输入:<code>ssd1306</code>关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 <code>Adafruit SSD1306</code>对应的 <code>2</code>选项,进入点击 <code>y</code> 使能:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184834403" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184930394" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p>这样我们就成功把 <code>Adafruit SSD1306</code> 示例库下载到本地了,同时还有一下依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453.png" +width="1720" +height="772" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123185120453" +class="gallery-image" +data-flex-grow="222" +data-flex-basis="534px" +></p> +<p>我们找到路径:<code>rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c</code>,可以看到该文件夹下有一个<code>ssd1306_128x64_i2c.ino</code>文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的<code>arduino_main.cpp</code>文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board<span class="se">\b</span>oard<span class="se">\r</span>tduino<span class="se">\a</span>rduino_main.cpp +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span><span class="lnt">267 +</span><span class="lnt">268 +</span><span class="lnt">269 +</span><span class="lnt">270 +</span><span class="lnt">271 +</span><span class="lnt">272 +</span><span class="lnt">273 +</span><span class="lnt">274 +</span><span class="lnt">275 +</span><span class="lnt">276 +</span><span class="lnt">277 +</span><span class="lnt">278 +</span><span class="lnt">279 +</span><span class="lnt">280 +</span><span class="lnt">281 +</span><span class="lnt">282 +</span><span class="lnt">283 +</span><span class="lnt">284 +</span><span class="lnt">285 +</span><span class="lnt">286 +</span><span class="lnt">287 +</span><span class="lnt">288 +</span><span class="lnt">289 +</span><span class="lnt">290 +</span><span class="lnt">291 +</span><span class="lnt">292 +</span><span class="lnt">293 +</span><span class="lnt">294 +</span><span class="lnt">295 +</span><span class="lnt">296 +</span><span class="lnt">297 +</span><span class="lnt">298 +</span><span class="lnt">299 +</span><span class="lnt">300 +</span><span class="lnt">301 +</span><span class="lnt">302 +</span><span class="lnt">303 +</span><span class="lnt">304 +</span><span class="lnt">305 +</span><span class="lnt">306 +</span><span class="lnt">307 +</span><span class="lnt">308 +</span><span class="lnt">309 +</span><span class="lnt">310 +</span><span class="lnt">311 +</span><span class="lnt">312 +</span><span class="lnt">313 +</span><span class="lnt">314 +</span><span class="lnt">315 +</span><span class="lnt">316 +</span><span class="lnt">317 +</span><span class="lnt">318 +</span><span class="lnt">319 +</span><span class="lnt">320 +</span><span class="lnt">321 +</span><span class="lnt">322 +</span><span class="lnt">323 +</span><span class="lnt">324 +</span><span class="lnt">325 +</span><span class="lnt">326 +</span><span class="lnt">327 +</span><span class="lnt">328 +</span><span class="lnt">329 +</span><span class="lnt">330 +</span><span class="lnt">331 +</span><span class="lnt">332 +</span><span class="lnt">333 +</span><span class="lnt">334 +</span><span class="lnt">335 +</span><span class="lnt">336 +</span><span class="lnt">337 +</span><span class="lnt">338 +</span><span class="lnt">339 +</span><span class="lnt">340 +</span><span class="lnt">341 +</span><span class="lnt">342 +</span><span class="lnt">343 +</span><span class="lnt">344 +</span><span class="lnt">345 +</span><span class="lnt">346 +</span><span class="lnt">347 +</span><span class="lnt">348 +</span><span class="lnt">349 +</span><span class="lnt">350 +</span><span class="lnt">351 +</span><span class="lnt">352 +</span><span class="lnt">353 +</span><span class="lnt">354 +</span><span class="lnt">355 +</span><span class="lnt">356 +</span><span class="lnt">357 +</span><span class="lnt">358 +</span><span class="lnt">359 +</span><span class="lnt">360 +</span><span class="lnt">361 +</span><span class="lnt">362 +</span><span class="lnt">363 +</span><span class="lnt">364 +</span><span class="lnt">365 +</span><span class="lnt">366 +</span><span class="lnt">367 +</span><span class="lnt">368 +</span><span class="lnt">369 +</span><span class="lnt">370 +</span><span class="lnt">371 +</span><span class="lnt">372 +</span><span class="lnt">373 +</span><span class="lnt">374 +</span><span class="lnt">375 +</span><span class="lnt">376 +</span><span class="lnt">377 +</span><span class="lnt">378 +</span><span class="lnt">379 +</span><span class="lnt">380 +</span><span class="lnt">381 +</span><span class="lnt">382 +</span><span class="lnt">383 +</span><span class="lnt">384 +</span><span class="lnt">385 +</span><span class="lnt">386 +</span><span class="lnt">387 +</span><span class="lnt">388 +</span><span class="lnt">389 +</span><span class="lnt">390 +</span><span class="lnt">391 +</span><span class="lnt">392 +</span><span class="lnt">393 +</span><span class="lnt">394 +</span><span class="lnt">395 +</span><span class="lnt">396 +</span><span class="lnt">397 +</span><span class="lnt">398 +</span><span class="lnt">399 +</span><span class="lnt">400 +</span><span class="lnt">401 +</span><span class="lnt">402 +</span><span class="lnt">403 +</span><span class="lnt">404 +</span><span class="lnt">405 +</span><span class="lnt">406 +</span><span class="lnt">407 +</span><span class="lnt">408 +</span><span class="lnt">409 +</span><span class="lnt">410 +</span><span class="lnt">411 +</span><span class="lnt">412 +</span><span class="lnt">413 +</span><span class="lnt">414 +</span><span class="lnt">415 +</span><span class="lnt">416 +</span><span class="lnt">417 +</span><span class="lnt">418 +</span><span class="lnt">419 +</span><span class="lnt">420 +</span><span class="lnt">421 +</span><span class="lnt">422 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/* +</span></span><span class="line"><span class="cl"> * Copyright <span class="o">(</span>c<span class="o">)</span> 2006-2023, RT-Thread Development Team +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * SPDX-License-Identifier: Apache-2.0 +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * Change Logs: +</span></span><span class="line"><span class="cl"> * Date Author Notes +</span></span><span class="line"><span class="cl"> * 2023-10-28 Wangyuqiang first version +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Arduino.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;SPI.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Wire.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_GFX.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_SSD1306.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_WIDTH 128 // OLED display width, in pixels</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_HEIGHT 64 // OLED display height, in pixels</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// Declaration <span class="k">for</span> an SSD1306 display connected to I2C <span class="o">(</span>SDA, SCL pins<span class="o">)</span> +</span></span><span class="line"><span class="cl">// The pins <span class="k">for</span> I2C are defined by the Wire-library. +</span></span><span class="line"><span class="cl">// On an arduino UNO: A4<span class="o">(</span>SDA<span class="o">)</span>, A5<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino MEGA 2560: 20<span class="o">(</span>SDA<span class="o">)</span>, 21<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino LEONARDO: 2<span class="o">(</span>SDA<span class="o">)</span>, 3<span class="o">(</span>SCL<span class="o">)</span>, ... +</span></span><span class="line"><span class="cl"><span class="c1">#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_ADDRESS 0x3C ///&lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32</span> +</span></span><span class="line"><span class="cl">Adafruit_SSD1306 display<span class="o">(</span>SCREEN_WIDTH, SCREEN_HEIGHT, <span class="p">&amp;</span>Wire, OLED_RESET<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define NUMFLAKES 10 // Number of snowflakes in the animation example</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_HEIGHT 16</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_WIDTH 16</span> +</span></span><span class="line"><span class="cl">static const unsigned char PROGMEM logo_bmp<span class="o">[]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="o">{</span> 0b00000000, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11110011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11111110, 0b11111000, +</span></span><span class="line"><span class="cl"> 0b01111110, 0b11111111, +</span></span><span class="line"><span class="cl"> 0b00110011, 0b10011111, +</span></span><span class="line"><span class="cl"> 0b00011111, 0b11111100, +</span></span><span class="line"><span class="cl"> 0b00001101, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00011011, 0b10100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01111100, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01110000, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00000000, 0b00110000 <span class="o">}</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void setup<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.begin<span class="o">(</span>115200<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // <span class="nv">SSD1306_SWITCHCAPVCC</span> <span class="o">=</span> generate display voltage from 3.3V internally +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span>!display.begin<span class="o">(</span>SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS<span class="o">))</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;SSD1306 allocation failed&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span><span class="p">;</span> // Don<span class="s1">&#39;t proceed, loop forever +</span></span></span><span class="line"><span class="cl"><span class="s1"> } +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show initial display buffer contents on the screen -- +</span></span></span><span class="line"><span class="cl"><span class="s1"> // the library initializes this with an Adafruit splash screen. +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); // Pause for 2 seconds +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Clear the buffer +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.clearDisplay(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Draw a single pixel in white +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.drawPixel(10, 10, SSD1306_WHITE); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show the display buffer on the screen. You MUST call display() after +</span></span></span><span class="line"><span class="cl"><span class="s1"> // drawing commands to make them visible on screen! +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); +</span></span></span><span class="line"><span class="cl"><span class="s1"> // display.display() is NOT necessary after every single drawing command, +</span></span></span><span class="line"><span class="cl"><span class="s1"> // unless that&#39;</span>s what you want...rather, you can batch up a bunch of +</span></span><span class="line"><span class="cl"> // drawing operations and <span class="k">then</span> update the screen all at once by calling +</span></span><span class="line"><span class="cl"> // display.display<span class="o">()</span>. These examples demonstrate both approaches... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawtriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfilltriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawchar<span class="o">()</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawstyles<span class="o">()</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testscrolltext<span class="o">()</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawbitmap<span class="o">()</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Invert and restore display, pausing in-between +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">false</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testanimate<span class="o">(</span>logo_bmp, LOGO_WIDTH, LOGO_HEIGHT<span class="o">)</span><span class="p">;</span> // Animate bitmaps +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void loop<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int16_t i<span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn line +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.width<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> <span class="m">2</span> seconds +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so rectangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-i*2, display.height<span class="o">()</span>-i*2, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawCircle<span class="o">(</span>display.width<span class="o">()</span>/2, display.height<span class="o">()</span>/2, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so circles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillCircle<span class="o">(</span>display.width<span class="o">()</span> / 2, display.height<span class="o">()</span> / 2, i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn circle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so round-rects alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so triangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0, 0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.cp437<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> // Use full <span class="m">256</span> char <span class="s1">&#39;Code Page 437&#39;</span> font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Not all the characters will fit on the display. This is normal. +</span></span><span class="line"><span class="cl"> // Library will draw what it can and the rest will be clipped. +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;256<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span><span class="nv">i</span> <span class="o">==</span> <span class="s1">&#39;\n&#39;</span><span class="o">)</span> display.write<span class="o">(</span><span class="s1">&#39; &#39;</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> display.write<span class="o">(</span>i<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0,0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_BLACK, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;inverse&#39;</span> text +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>3.141592<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;0x&#34;</span><span class="o">))</span><span class="p">;</span> display.println<span class="o">(</span>0xDEADBEEF, HEX<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>10, 0<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;scroll&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show initial text +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>100<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Scroll in various directions, pausing in-between: +</span></span><span class="line"><span class="cl"> display.startscrollright<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrollleft<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagright<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagleft<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span> +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.width<span class="o">()</span> - LOGO_WIDTH <span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.height<span class="o">()</span> - LOGO_HEIGHT<span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define XPOS 0 // Indexes into the &#39;icons&#39; array in function below</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define YPOS 1</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define DELTAY 2</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int8_t f, icons<span class="o">[</span>NUMFLAKES<span class="o">][</span>3<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Initialize <span class="s1">&#39;snowflake&#39;</span> positions +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;x: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; y: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; dy: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span> <span class="o">{</span> // Loop forever... +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear the display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Draw each snowflake: +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, bitmap, w, h, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show the display buffer on the screen +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>200<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> 1/10 second +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Then update coordinates of each flake... +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> +<span class="o">=</span> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> // If snowflake is off the bottom of the screen... +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> &gt;<span class="o">=</span> display.height<span class="o">())</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // Reinitialize to a random position, just off the top +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在此示例中有几点注意事项:</p> +<ul> +<li>在每一份添加的示例工程中,我们都必须要包含头文件 <code>#include &lt;Arduino.h&gt;</code></li> +<li>由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 <code>0x3c</code>,所以对应示例工程中的 <code>SCREEN_ADDRESS</code>需要修改为 <code>0X3C</code></li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061.png" +width="533" +height="143" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190157061" +class="gallery-image" +data-flex-grow="372" +data-flex-basis="894px" +></p> +<ul> +<li>由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍</li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190348607" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:</p> +<table> +<thead> +<tr> +<th style="text-align:center">pin</th> +<th style="text-align:center">func</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">P203</td> +<td style="text-align:center">i2c0-sda</td> +</tr> +<tr> +<td style="text-align:center">P202</td> +<td style="text-align:center">i2c0-scl</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">vcc</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">gnd</td> +</tr> +</tbody> +</table> +<p>接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695.png" +width="813" +height="431" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123191534695" +class="gallery-image" +data-flex-grow="188" +data-flex-basis="452px" +></p> +<p>查看demo:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo.gif" +width="1280" +height="720" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif 1024w" +loading="lazy" +alt="demo" +class="gallery-image" +data-flex-grow="177" +data-flex-basis="426px" +></p>【Micro_ROS】在RT-Thread上运行micro_roshttps://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/<img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/cover.jpg" alt="Featured image of post 【Micro_ROS】在RT-Thread上运行micro_ros" /><h1 id="快速上手micro-ros--rt-threadserial和udp方式">快速上手micro ros &amp;&amp; RT-Thread(serial和udp方式) +</h1><h2 id="1背景介绍">1.背景介绍 +</h2><p>Micro-ROS(Micro Robot Operating System)是ROS 2(Robot Operating System 2)的嵌入式版本,专门设计用于在嵌入式系统中运行,以支持机器人和嵌入式设备的实时控制和通信。Micro-ROS的目标是将ROS 2的强大功能扩展到资源受限的嵌入式平台,例如微控制器和嵌入式系统。</p> +<p>Micro-ROS的出现使得嵌入式系统和机器人应用能够更紧密地与ROS 2生态系统集成,从而实现更高级别的机器人自动化和控制。它为开发人员提供了一种在嵌入式环境中构建复杂机器人系统的方法,无论是在无人机、自动导航车辆还是其他嵌入式控制应用方面。</p> +<ul> +<li>micro ros分层模块架构</li> +</ul> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png.webp" +width="955" +height="611" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/a423ac1b736d4b4905aa5ca886288bb1.png_hu6a00f0a2e4e4902b4fd40b8698bda3f7_47184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +class="gallery-image" +data-flex-grow="156" +data-flex-basis="375px" +></p> +<p>以下是Micro-ROS的一些关键特点和概念:</p> +<ol> +<li> +<p><strong>嵌入式系统支持:</strong> Micro-ROS旨在在嵌入式系统上运行,包括微控制器和其他资源受限的硬件。它提供了一个轻量级的ROS 2堆栈,以便将ROS 2功能集成到这些系统中。</p> +</li> +<li> +<p><strong>实时性和硬件抽象:</strong> Micro-ROS支持实时性需求,使其适用于对实时性要求较高的应用程序。此外,它提供了硬件抽象层(HAL),允许在不同嵌入式平台上使用相同的ROS 2代码。</p> +</li> +<li> +<p><strong>通信和中间件:</strong> Micro-ROS使用ROS 2通信机制,因此可以无缝地与其他ROS 2系统通信。它支持多种通信方式,包括串口、UDP、以太网等。</p> +</li> +<li> +<p><strong>适用于机器人和自动化:</strong> Micro-ROS的主要应用领域包括机器人和自动化系统。通过将ROS 2的能力引入嵌入式系统,开发人员可以更轻松地构建具有传感器、执行器和通信需求的机器人应用。</p> +</li> +<li> +<p><strong>可扩展性:</strong> Micro-ROS可以根据应用程序的需求进行扩展和定制。开发人员可以选择要包括的ROS 2功能和模块,以适应其特定应用场景。</p> +</li> +<li> +<p><strong>开源:</strong> Micro-ROS是开源项目,遵循ROS 2的开源精神。这意味着开发人员可以自由地访问、使用和贡献到该项目。</p> +</li> +</ol> +<p>本文将教你如何快速上手使用如何在 RT-Thread上运行 micro-ros,使用包括串口(serial)和UDP两种通信方式与主机 ROS 通信。</p> +<h2 id="2工程准备工作">2.工程准备工作 +</h2><h3 id="21-克隆-rt-thread主仓">2.1 克隆 RT-Thread主仓 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone https://github.com/RT-Thread/rt-thread.git +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="22-克隆-env-windows">2.2 克隆 env-windows +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone --recursive --depth <span class="m">1</span> https://github.com/RT-Thread/env-windows.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆下来的 env-windows 可以放在D盘,同时双击打开 <code>env.exe</code>,待启动<code>ConEmu</code>终端后将其注册到鼠标右键快捷方式</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png.webp" +width="1200" +height="613" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/8f8f553cdc83a2b2ed52dec898ef5b30.png_hu0c5e2619e8e8fdeb0fb2aa2d4b668012_74272_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="195" +data-flex-basis="469px" +></p> +<h2 id="3编译准备工作">3.编译准备工作 +</h2><h3 id="31-python--cmake安装">3.1 python &amp; cmake安装 +</h3><p>首先去官网安装如下工具:</p> +<ul> +<li>python(大于python36):https://www.python.org/downloads/windows/</li> +<li>cmake(大于v3.22):https://cmake.org/files/</li> +</ul> +<h3 id="32-scons工具安装">3.2 scons工具安装 +</h3><p>打开 windows powershell ,使用 python 安装 scons</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip3 install scons +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="33-gnu-make安装">3.3 GNU make安装 +</h3><p>GNU make 的安装可以参考该 issue 的三种方式</p> +<ul> +<li><a class="link" href="https://github.com/kurisaW/micro_ros_rtthread_component/issues/5" target="_blank" rel="noopener" +>https://github.com/kurisaW/micro_ros_rtthread_component/issues/5</a></li> +</ul> +<p>这里我选择的是使用choco安装make,打开windows powershell(管理员):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ Set-ExecutionPolicy Bypass -Scope Process -Force<span class="p">;</span> iex <span class="o">((</span>New-Object System.Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">&#39;https://chocolatey.org/install.ps1&#39;</span><span class="o">))</span> +</span></span><span class="line"><span class="cl">$ choco install make +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="34-fastgithub安装">3.4 Fastgithub安装 +</h3><p>为了防止在后续下载 micro ros 过程中 GitHub 仓库拉取失败,可以下一个 Fastgithub 来加速 GitHub</p> +<ul> +<li><a class="link" href="https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip" target="_blank" rel="noopener" +>https://github.com/dotnetcore/FastGithub/releases/download/2.1.4/fastgithub_win-x64.zip</a></li> +</ul> +<h2 id="4工程配置">4.工程配置 +</h2><p>选择一份 bsp 进行 micro_ros 的开发,这里我使用的是 RTT 最近出的星火Spark</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> .<span class="se">\r</span>t-thread<span class="se">\b</span>sp<span class="se">\s</span>tm32<span class="se">\s</span>tm32f407-rt-spark +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="41-指定工具链">4.1 指定工具链 +</h3><p>去官网下载 <code>gcc-arm-none-eabi-10-2020-q4-major-win32</code>工具链,注意不用配置到环境变量中,以免发生冲突</p> +<ul> +<li><a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>gcc-arm-none-eabi-10-2020-q4-major-win32.exe</a></li> +</ul> +<p>修改 bsp 工程下的 rtconfig.py 文件,指定 gcc 工具链</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/1d3e7d151768600f29b406114fe88ff2.png_hud8f517075f04d3965230e805acd5126a_75502_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h3 id="42-micro_ros-软件包配置">4.2 micro_ros 软件包配置 +</h3><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ConEmu 执行如下命令生成 packages 目录</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> packages +</span></span></code></pre></td></tr></table> +</div> +</div><p>克隆 micro_ros 配置仓库</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git clone -b win_arm-gcc https://github.com/kurisaW/micro_ros_rtthread_component.git +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们来看下目录层次:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├─micro_ros_rtthread_component +</span></span><span class="line"><span class="cl">│ ├─.images +</span></span><span class="line"><span class="cl">│ ├─builder +</span></span><span class="line"><span class="cl">│ │ ├─extra_packages +</span></span><span class="line"><span class="cl">│ │ ├─metas +</span></span><span class="line"><span class="cl">│ │ ├─microros_utils +</span></span><span class="line"><span class="cl">│ │ └─patchs +</span></span><span class="line"><span class="cl">│ │ ├─foxy +</span></span><span class="line"><span class="cl">│ │ └─humble +</span></span><span class="line"><span class="cl">│ ├─docs +</span></span><span class="line"><span class="cl">│ ├─examples +</span></span><span class="line"><span class="cl">│ ├─include +</span></span><span class="line"><span class="cl">│ ├─package +</span></span><span class="line"><span class="cl">│ │ └─micro_ros_rtthread_package +</span></span><span class="line"><span class="cl">│ └─src +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要将<code>micro_ros_rtthread_package</code>目录复制一份到<code>..\env-windows\packages</code>目录下,同时修改<code>..\env-windows\packages\Kconfig</code>内容如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">source &#34;$PKGS_DIR/packages/Kconfig&#34; +</span></span><span class="line"><span class="cl">source &#34;$PKGS_DIR/micro_ros_rtthread_package/Kconfig&#34; +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="43-指定cmake编译工具链">4.3 指定Cmake编译工具链 +</h3><p>想要在 RT-Thread 中使用 micro_ros ,需要先通过 Cmake 编译得到一份 <code>libmicroros.a</code>静态链接库文件,下面是 micro_ros Cmake 的相关配置:</p> +<p>回到目录:<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code></p> +<p>使用 ENV 生成 CMakeLists.txt 文件,里面包含了工程的配置编译选项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons --target<span class="o">=</span>cmake +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在当前目录下就可以看见一个 <code>CMakeLists.txt</code>文件了,同时我们进入目录<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark\packages\micro_ros_rtthread_component\builder</code>,找到<code>toolchain.cmake</code>文件,参考前面生成的<code>CMakeLists.txt</code>文件修改<code>toolchain.cmake</code></p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png.webp" +width="1200" +height="447" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94877df6c4caa43c69c1a1beb59bedfd.png_huced1339d60db3d9f500b5281fd50a464_53778_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="268" +data-flex-basis="644px" +></p> +<h3 id="44-micro-ros-在-env-中的配置">4.4 micro ros 在 ENV 中的配置 +</h3><p>再次回到<code>..\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,打开 ENV 勾选配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>*<span class="o">]</span> micro-ROS package <span class="k">for</span> RTThread +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Include examples +</span></span><span class="line"><span class="cl"> Distribution <span class="o">(</span>Foxy<span class="o">)</span> ---&gt; +</span></span><span class="line"><span class="cl"> Memory configuration ---&gt; +</span></span><span class="line"><span class="cl"> ROS node communication mode <span class="o">(</span>serial<span class="o">)</span> ---&gt; +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中在<code>Memory configuration</code>中的<code>Publishers</code>和<code>Subscribers</code>这两个参数值要求大于2,因为在 micro_ros 的示例工程:micro_ros_ping_pong要求至少两个发布者和两个订阅者,同时我们选择通信模式为 <code>serial</code></p> +<p>此外,我们需要一个串口进行通信,根据板载情况勾选一个串口设备,并确保该串口成功创建!!</p> +<p>同时我们使用 vscode 打开文件<code>packages\micro_ros_rtthread_component\src\rtt_serial_transport.c</code>,搜索宏<code>MICRO_ROS_SERIAL_NAME</code>并修改为你新创建的串口设备名。</p> +<h2 id="5开始编译">5.开始编译 +</h2><p>回到<code>.\rt-thread\bsp\stm32\stm32f407-rt-spark</code>目录下,鼠标右键打开 windows powershell ,输入如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">scons --build_microros +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们就可以看到 python 会自动安装依赖包并且开始下载 microros所需的依赖库,并且该依赖库的安装位置位于 <code>C:\Users\$user\AppData\Local\Temp\micro</code>下</p> +<p>这里的配置项主要位于<code>packages\micro_ros_rtthread_component\builder\SConscript</code>文件中,由于不同的工具链和平台所使用的一些标准C库函数有些不同差异,所以目前是基于 cortex-M4 适配了 micro_ros 库,在<code>packages\micro_ros_rtthread_component\builder\microros_utils\repositories.py</code>文件中更改了一些仓库分支为我修改的仓库分支,后续会以补丁文件的形式发布</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/5f8d170d4a726855cf680c2d7a84681d.png_hu51cce00e6e918a985c5f6ba6ead140df_143198_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>编译完成后会使用 ar 将所有依赖的 micro_ros 库文件静态链接成 <code>packages\micro_ros_rtthread_component\builder\libmicroros\libmicroros.a</code>文件,同时将<code>C:\Users\20537\AppData\Local\Temp\micro\mcu\install\include</code>目录复制到<code>packages\micro_ros_rtthread_component\builder\libmicroros\include</code>目录下</p> +<p>编译完成后我们就得到了 rt-thread.elf 文件,可以使用 STM32CubeProgrammer 工具进行烧录到星火Spark上</p> +<p>附:这里说下 GCC-AR 是什么:GCC-AR 是 <strong>gcc配套的库管理工具</strong>,它可以创建,修改和提取静态库(.a文件)。 通过使用 GCC-AR,可以将多个相关的对象文件(.o文件)打包成一个静态库,以方便在后续的编译过程中重复使用这些对象文件。</p> +<p><img src="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/micro_ros%E5%9C%A8rt-thread%E4%B8%8A%E8%BF%90%E8%A1%8Cmicro_ros/figure/94983d06a46f6dd3d2a5c800577ab7fa.png_hu44ca883a94ec9b49f7834d5fb288b2c4_136972_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<h2 id="6wsl安装及-usbipd-支持">6.WSL安装及 usbipd 支持 +</h2><ul> +<li> +<p>WSL安装:WSL的安装具体可以看网上怎么操作的,此处不再赘述</p> +</li> +<li> +<p>Docker安装:打开 wsl 终端,使用官网脚本一键安装即可</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -fsSL https://test.docker.com -o test-docker.sh +</span></span><span class="line"><span class="cl">$ sudo sh test-docker.sh +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>usbipd支持</li> +</ul> +<p>请参考这篇文章完成 usbipd 的支持:https://club.rt-thread.org/ask/article/8671e03210f950a7.html</p> +<h2 id="7serial测试">7.serial测试 +</h2><p>此处仅给出相关命令,具体流程请参考演示视频:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># windows powershell端</span> +</span></span><span class="line"><span class="cl">$ usbipd wsl list // 查看系统USB设备列表 +</span></span><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;usb-id&#34;</span> // 连接usb至wsl +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># wsl ubuntu20.04(注意:目前支持的microros版本:foxy支持的ubuntu版本为ubuntu20.04)</span> +</span></span><span class="line"><span class="cl">$ sudo docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial --dev /dev/ttyACM0 // 运行docker microros:foxy代理 +</span></span><span class="line"><span class="cl">$ ros2 topic list // 查看ros topic列表 +</span></span><span class="line"><span class="cl">$ ros2 topic <span class="nb">echo</span> /micro_ros_rtt_subscriber // 打印话题详情 +</span></span><span class="line"><span class="cl">$ ros2 topic pub /micro_ros_rtt_subscriber std_msgs/msg/Int32 data:<span class="se">\ </span>10 // 发布topic data值为10 +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1se41197Ea?t=3.8" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="8udp4测试">8.udp4测试 +</h2><h3 id="81-准备工作">8.1 准备工作 +</h3><p>首先需要在linux本地 搭建好 ROS 环境,micro-ros环境的安装参考**<a class="link" href="https://fishros.com/d2lros2foxy/#/chapt2/2.3ROS2%E7%9A%84%E5%AE%89%E8%A3%85" target="_blank" rel="noopener" +>鱼香大佬的网站</a>**</p> +<p><strong>注意:我们安装的ros版本为 <code>ros:foxy</code></strong></p> +<p>继续搭建 micro-ros 构建环境,打开linux终端,按照如下步骤一步步走:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 激活ros:foxy环境</span> +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> /opt/ros/foxy/setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建工作区并拉取micro_ros_setup仓库</span> +</span></span><span class="line"><span class="cl">$ mkdir /home/<span class="nv">$user</span>/microros_ws <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /home/<span class="nv">$user</span>/microros_ws +</span></span><span class="line"><span class="cl">$ git clone -b foxy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 更新rosdep</span> +</span></span><span class="line"><span class="cl">$ sudo apt update +</span></span><span class="line"><span class="cl">$ <span class="nb">export</span> <span class="nv">ROSDISTRO_INDEX_URL</span><span class="o">=</span>https://mirrors.tuna.tsinghua.edu.cn/rosdistro/index-v4.yaml +</span></span><span class="line"><span class="cl">$ rosdep update --include-eol-distros +</span></span><span class="line"><span class="cl">$ rosdep install --from-paths src --ignore-src -y +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo apt-get install python3-pip +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># colcon编译</span> +</span></span><span class="line"><span class="cl">$ colcon build +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">ps:如果提示找不到colcon命令,使用如下方式安装colcon +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt install python3-colcon-common-externsions <span class="c1"># linux</span> +</span></span><span class="line"><span class="cl">python3 -m pip install colcon-common-externsions <span class="c1"># macos</span> +</span></span><span class="line"><span class="cl">pip install -U colcon-commmon-externsions <span class="c1"># windows</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建一份固件工作区</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_firmware_ws.sh host +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建固件</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_firmware.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 创建microros代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup create_agent_ws.sh +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 构建代理</span> +</span></span><span class="line"><span class="cl">$ ros2 run micro_ros_setup build_agent.sh +</span></span><span class="line"><span class="cl">$ <span class="nb">source</span> install/local_setup.bash +</span></span></code></pre></td></tr></table> +</div> +</div><p>完成上述工作后我们micro ros的代理环境就准备就绪了</p> +<h3 id="82-以-udp-方式开启micro_ros-代理">8.2 以 UDP 方式开启micro_ros 代理 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ros2 run micro_ros_agent micro_ros_agent udp4 --port <span class="m">9999</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="83-udp测试流程">8.3 udp测试流程 +</h3><p>这里就不讲详细的配置了,具体过程请看下方链接:</p> +<p><strong>演示视频:<a class="link" href="https://www.bilibili.com/video/BV1h84y1R7P6?t=2.6" target="_blank" rel="noopener" +>[点击此处精准空降: microros_rtt_serial]</a></strong></p> +<h2 id="9几点说明">9.几点说明 +</h2><ul> +<li> +<p>为什么编译不使用 ConEmu :因为 ConEmu 内部集成的是 python27 ,而 micro_ros 编译所需的 python 版本最低为 python36,建议使用 python38 及以上版本</p> +</li> +<li> +<p>如果是使用的串口方式通信,不推荐在虚拟机上运行docker microros 代理,虚拟机似乎会造成消息的多次转发,导致无法正常接收到数据,建议使用 windows wsl服务</p> +</li> +<li> +<p>如果是使用UDP通信的话,并且在wsl中运行 agent ,需要允许 WLS 的出入站规则,可以打开windows powershell ,并输入如下代码:</p> +</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 允许 WSL 入站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Inbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 允许 WSL 出站规则,请打开 Windows PowerShell ,并输入如下命令</span> +</span></span><span class="line"><span class="cl">$ New-NetFirewallRule -DisplayName <span class="s2">&#34;WSL&#34;</span> -Direction Outbound -InterfaceAlias <span class="s2">&#34;vEthernet (WSL)&#34;</span> -Action Allow +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p>如果使用udp通信不建议使用docker运行agent,docker不能直接外部访问IP,建议还是在linux本地搭建好 micro-ros代理环境</p> +</li> +<li> +<p>具体的实现细节在此处没有具体说明,如果是基于其他平台移植,并且想要一起学习的可以艾特我一起讨论,后面会考虑对多个架构进行支持适配</p> +</li> +</ul>RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div>RT-Thread内核宏定义详解(rtdef.h)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/Sun, 09 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E5%86%85%E6%A0%B8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%AF%A6%E8%A7%A3rtdef.h/cover.jpg" alt="Featured image of post RT-Thread内核宏定义详解(rtdef.h)" /><h4 id="1rt-thread版本信息">1.RT-Thread版本信息 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread version information */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_VERSION 4 </span><span class="cm">/**&lt; major version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SUBVERSION 1 </span><span class="cm">/**&lt; minor version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_REVISION 1 </span><span class="cm">/**&lt; revise version number */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread version */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>使用方法:可用于bsp指定RT-Thread版本</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#if (RTTHREAD_VERSION &gt;= RT_VERSION_CHECK(4, 1, 0) */ +</span></span><span class="line"><span class="cl">#define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \ +</span></span><span class="line"><span class="cl"> (minor * 100) + revise) +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2rt-thrad基础数据类型定义">2.RT-Thrad基础数据类型定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread basic data type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_ARCH_DATA_TYPE </span><span class="cm">/* 简单来说,开启此宏定义后,BSP就会在ARCH_CPU 级别定义基本数据类型 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC </span><span class="cm">/* 用于控制是否使用标准C库函数 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">int8_t</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int16_t</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int32_t</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint8_t</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint16_t</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint32_t</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int64_t</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">uint64_t</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">size_t</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">char</span> <span class="kt">rt_int8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">short</span> <span class="kt">rt_int16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">int</span> <span class="kt">rt_int32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="kt">rt_uint8_t</span><span class="p">;</span> <span class="cm">/**&lt; 8bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="kt">rt_uint16_t</span><span class="p">;</span> <span class="cm">/**&lt; 16bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_uint32_t</span><span class="p">;</span> <span class="cm">/**&lt; 32bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef ARCH_CPU_64BIT </span><span class="cm">/* 判断当前程序运行的CPU架构是否为64位 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">typedef</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_int64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">rt_uint64_t</span><span class="p">;</span> <span class="cm">/**&lt; 64bit unsigned integer type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="kt">rt_size_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for size number */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* ARCH_CPU_64BIT */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_ARCH_DATA_TYPE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int</span> <span class="kt">rt_bool_t</span><span class="p">;</span> <span class="cm">/**&lt; boolean type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">rt_base_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit CPU related date type */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">rt_ubase_t</span><span class="p">;</span> <span class="cm">/**&lt; Nbit unsigned CPU related data type */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_err_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for error number */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_time_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for time stamp */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_uint32_t</span> <span class="kt">rt_tick_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for tick count */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_flag_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for flags */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_ubase_t</span> <span class="kt">rt_dev_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for device */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">rt_base_t</span> <span class="kt">rt_off_t</span><span class="p">;</span> <span class="cm">/**&lt; Type for offset */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* boolean type definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TRUE 1 </span><span class="cm">/**&lt; boolean true */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_FALSE 0 </span><span class="cm">/**&lt; boolean fails */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* null pointer definition */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_NULL 0 +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li> +<p><code>rt_base_t</code>:为了使代码可以<strong>在不同的CPU上移植并保持向后兼容性</strong>。<code>long</code>类型的位数(bit数)可能因不同的CPU体系结构而有所不同,但是使用<code>rt_base_t</code>代替<code>long</code>可以隐藏这种差异,以实现代码的可移植性。(rt_ubase_t原理相同)</p> +</li> +<li> +<p><code>rt_err_t</code>:代表<strong>错误码</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_time_t</code>:代表<strong>时间戳</strong>的数据类型,这里使用了<code>rt_uint32_t</code>作为它的别名。<code>rt_uint32_t</code>是一个32位无符号整数类型,可以用来表示1970年1月1日以来的秒数。</p> +</li> +<li> +<p><code>rt_tick_t</code>:代表<strong>系统时钟节拍计数</strong>的数据类型,这里也使用了<code>rt_uint32_t</code>作为它的别名。在嵌入式系统中,通常会使用硬件定时器来产生一个固定频率的中断信号,并且在每次中断时对<code>rt_tick_t</code>进行递增操作,从而实现对时间的计数。</p> +</li> +<li> +<p><code>rt_flag_t</code>:代表<strong>标志位</strong>的数据类型,这里使用了之前定义的<code>rt_base_t</code>作为它的别名。</p> +</li> +<li> +<p><code>rt_dev_t</code>:代表<strong>设备号</strong>的数据类型,这里使用了<code>rt_ubase_t</code>作为它的别名。在嵌入式系统中,通常会有多个外设需要使用不同的设备号进行标识,因此需要定义一个数据类型来保存设备号。</p> +</li> +<li> +<p><code>rt_off_t</code>:代表<strong>偏移量</strong>的数据类型,这里也使用了之前定义的<code>rt_base_t</code>作为它的别名。在文件系统中,通常需要记录某个文件中的偏移量(即当前读写位置),因此需要定义一个数据类型来保存偏移量。</p> +</li> +</ul> +<h4 id="3rt-thread基本数据类型的范围">3.RT-Thread基本数据类型的范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of base type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX UINT8_MAX </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX UINT16_MAX </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX UINT32_MAX </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT8_MAX 0xff </span><span class="cm">/**&lt; Maximum number of UINT8 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT16_MAX 0xffff </span><span class="cm">/**&lt; Maximum number of UINT16 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_UINT32_MAX 0xffffffff </span><span class="cm">/**&lt; Maximum number of UINT32 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>附:此处的<code>UINT8_MAX</code>、<code>UINT16_MAX</code>、<code>UINT32_MAX</code>为编译器预定的宏定义</p> +<h4 id="4rt-thread系统滴答时钟最大计数值">4.RT-Thread系统滴答时钟最大计数值 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TICK_MAX RT_UINT32_MAX </span><span class="cm">/**&lt; Maximum number of tick */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5rt-thread-ipc数据类型范围">5.RT-Thread IPC数据类型范围 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* maximum value of ipc type */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SEM_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of semaphore .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_VALUE_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mutex .value */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MUTEX_HOLD_MAX RT_UINT8_MAX </span><span class="cm">/**&lt; Maximum number of mutex .hold */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MB_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of mailbox .entry */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_MQ_ENTRY_MAX RT_UINT16_MAX </span><span class="cm">/**&lt; Maximum number of message queue .entry */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6rt-thread避免未使用变量警告">6.RT-Thread避免未使用变量警告 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_UNUSED(x) ((void)x) +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>**该宏定义表示将变量x强制转换为<code>void</code>类型,从而告诉编译器该变量未被使用,从而避免编译器发出“未使用变量”的警告。这种空操作常常用于函数参数或者结构体成员的声明中,因为有时候我们为了某些原因不得不声明一个变量,但在实际使用中却无需使用它,这时候就可以使用这个宏来标记变量未被使用。 **</p> +<p>下面是一个例子:假设在编写一个C语言程序时,需要使用qsort()函数进行数组排序。</p> +<p>该函数的第一个参数是一个void类型的指针,用于表示要排序的数组。</p> +<p>在实际使用中,我们可能并不需要使用这个参数。但是,由于该函数的参数列表中必须要有第一个参数,而且其类型为void*,因此我们不得不将一个无用的参数传递给函数,否则就会编译错误。</p> +<p>这时候,就可以使用RT_UNUSED宏来标记这个参数未被使用,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* sort code */</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">cmp</span><span class="p">);</span> <span class="c1">// 必须传递一个void*类型参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmp</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">RT_UNUSED</span><span class="p">(</span><span class="n">b</span><span class="p">);</span> <span class="c1">// 标记参数未使用 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这样就可以避免编译器报“未使用变量a/b”的警告了。</p> +<h4 id="7编译器相关定义">7.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_SECTION(x)</code>:表示<strong>将所修饰的数据/函数放置在指定的section中</strong>,x为section名字,通常是一个字符串。这个宏可以用于在程序中指定某些数据/函数位于特定的内存区域,比如放在Flash中或者RAM中,以满足不同的需求。该宏使用了GCC的语法扩展。</li> +<li><code>RT_USED</code>:表示<strong>告诉编译器保留所修饰的数据/函数</strong>,即使它没有被直接引用或调用。该宏通常用于防止删除不需要的代码和变量,以及确保所需的函数和变量在链接时能够正确地生成和调用。该宏使用了GCC的语法扩展。</li> +<li><code>ALIGN(n)</code>:表示<strong>将所修饰的数据/函数按照n字节对齐</strong>,即从地址0开始,每隔n个字节就对齐一次。该宏通常用于解决访问未对齐的数据导致的性能问题,以及操作系统中数据结构对齐的需求。该宏同样使用了GCC的语法扩展。</li> +<li><code>RT_WEAK</code>:表示<strong>将所修饰的数据/函数标记为弱引用</strong>,即该数据/函数可以被重定义。当出现多个同名的弱引用时,链接器会选择其中优先级最高的一个。该宏通常用于提供一些默认实现,但允许用户在需要时重写它们。该宏同样使用了GCC的语法扩展。</li> +<li><code>rt_inline</code>:表示<strong>将所修饰的函数定义为静态内联函数</strong>,即在编译时将函数的代码直接嵌入到调用处,以避免隐式调用带来的额外开销。该宏同样使用了GCC的语法扩展。</li> +</ul> +<h4 id="8编译器相关定义">8.编译器相关定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* Compiler Related Definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#if defined(__ARMCC_VERSION) </span><span class="cm">/* ARM Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* module compiling */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_MODULE +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllimport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API __declspec(dllexport) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_MODULE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__IAR_SYSTEMS_ICC__) </span><span class="cm">/* for IAR Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) @ x +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __root +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) PRAGMA(data_alignment=n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __weak +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__GNUC__) </span><span class="cm">/* GNU GCC Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef RT_USING_LIBC +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* the version of GNU GCC must be greater than 4.x */</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__builtin_va_list</span> <span class="n">__gnuc_va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="n">__gnuc_va_list</span> <span class="n">va_list</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define va_start(v,l) __builtin_va_start(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_end(v) __builtin_va_end(v) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define va_arg(v,l) __builtin_va_arg(v,l) +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_LIBC */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__ADSPBLACKFIN__) </span><span class="cm">/* for VisualDSP++ Compiler */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((aligned(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (_MSC_VER) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __declspec(align(n)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static __inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TI_COMPILER_VERSION__) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* The way that TI compiler set section is different from other(at least +</span></span></span><span class="line"><span class="cl"><span class="cm"> * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more +</span></span></span><span class="line"><span class="cl"><span class="cm"> * details. */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#elif defined (__TASKING__) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_SECTION(x) __attribute__((section(x))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_USED __attribute__((used, protect)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRAGMA(x) _Pragma(#x) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define ALIGN(n) __attribute__((__align(n))) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WEAK __attribute__((weak)) +</span></span></span><span class="line"><span class="cl"><span class="cp">#define rt_inline static inline +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RTT_API +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="cp">#error not supported tool chain +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* __ARMCC_VERSION */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ol> +<li><code>typedef __builtin_va_list __gnuc_va_list</code>: 定义了一个新类型<code>__gnuc_va_list</code>,并使用 <code>__builtin_va_list</code> 进行初始化。<code>__builtin_va_list</code> 是GCC内建的类型,用于表示可变参数列表中的参数,并在实现中进行处理。由于可变参数的实现和操作系统和编译器等因素相关,因此需要使用 <code>__builtin_va_list</code> 类型来实现可变参数列表。</li> +<li><code>typedef __gnuc_va_list va_list</code>: 定义了一个名为<code>va_list</code>的新类型,并将其重命名为<code>__gnuc_va_list</code>。</li> +<li><code>#define va_start(v,l) __builtin_va_start(v,l)</code>: 将 <code>va_start()</code> 重命名为 <code>__builtin_va_start()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_start()</code> 实现可变参数的功能。该宏的作用是对变参列表进行初始化,获取第一个参数的地址和类型,并返回可变参数队列中下一个参数的地址。</li> +<li><code>#define va_end(v) __builtin_va_end(v)</code>: 将 <code>va_end()</code> 重命名为 <code>__builtin_va_end()</code>,从而能够使用 GCC 内建的函数 <code>__builtin_va_end()</code> 实现可变参数的功能。该宏的作用是清除可变参数列表,并将其指针置为 NULL。</li> +<li><code>#define va_arg(v,l) __builtin_va_arg(v,l)</code>: 将 <code>va_arg()</code> 重命名为 <code>__builtin_va_arg()</code>,并使用 GCC 内建的函数 <code>__builtin_va_arg()</code> 实现可变参数的功能。该宏的作用是获取可变参数队列中的下一个参数,并将指针指向该参数的位置。</li> +<li><code>#define PRAGMA(x) _Pragma(#x)</code>:将参数<code>x</code>转化为字符串并使用<code>_Pragma()</code>将其作为编译指令执行。<code>_Pragma</code>是C99标准引入的一个新特性,它允许程序员在说明文件中进行诸如#pragma等命令式编译指令的嵌入式编程。而<code>#pragma</code>则是一种编译指令,用于控制编译器的一些行为,比如告诉编译器去链接某个库、指定编译器选项等。</li> +</ol> +<h4 id="9rt-thread错误码定义">9.RT-Thread错误码定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* RT-Thread error code definitions */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_EOK 0 </span><span class="cm">/**&lt; There is no error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ERROR 1 </span><span class="cm">/**&lt; A generic error happens */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ETIMEOUT 2 </span><span class="cm">/**&lt; Timed out */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EFULL 3 </span><span class="cm">/**&lt; The resource is full */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EEMPTY 4 </span><span class="cm">/**&lt; The resource is empty */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOMEM 5 </span><span class="cm">/**&lt; No memory */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_ENOSYS 6 </span><span class="cm">/**&lt; No system */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EBUSY 7 </span><span class="cm">/**&lt; Busy */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EIO 8 </span><span class="cm">/**&lt; IO error */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINTR 9 </span><span class="cm">/**&lt; Interrupted system call */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_EINVAL 10 </span><span class="cm">/**&lt; Invalid argument */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code>RT_EOK</code>:表示没有错误。</li> +<li><code>RT_ERROR</code>:表示发生了一般性的错误。</li> +<li><code>RT_ETIMEOUT</code>:表示超时错误。</li> +<li><code>RT_EFULL</code>:表示资源已满。</li> +<li><code>RT_EEMPTY</code>:表示资源为空。</li> +<li><code>RT_ENOMEM</code>:表示内存不足。</li> +<li><code>RT_ENOSYS</code>:表示没有该系统。</li> +<li><code>RT_EBUSY</code>:表示忙碌。</li> +<li><code>RT_EIO</code>:表示输入/输出错误。</li> +<li><code>RT_EINTR</code>:表示中断的系统调用。</li> +<li><code>RT_EINVAL</code>:表示无效的参数。</li> +</ul>【NXP】LPC55S69-Micropython移植日志https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/Mon, 06 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/<img src="https://kurisaw.github.io/p/nxplpc55s69-micropython%E7%A7%BB%E6%A4%8D%E6%97%A5%E5%BF%97/cover.jpg" alt="Featured image of post 【NXP】LPC55S69-Micropython移植日志" /><h2 id="简单了解micropython">简单了解Micropython +</h2><ul> +<li> +<p>MicroPython 是 Python 3 编程语言的一种精简而高效的实现,它包含 Python 标准库的一个子集,并被优化为在微控制器和受限环境中运行。</p> +</li> +<li> +<p>RT-Thread MicroPython 可以运行在任何搭载了 RT-Thread 操作系统并且有一定资源的嵌入式平台上。</p> +</li> +<li> +<p>MicroPython 可以运行在有一定资源的开发板上,给你一个低层次的 Python 操作系统,可以用来控制各种电子系统。</p> +</li> +<li> +<p>MicroPython 富有各种高级特性,比如交互式提示、任意精度整数、闭包函数、列表解析、生成器、异常处理等等。</p> +</li> +<li> +<p>MicroPython 的目标是尽可能与普通 Python 兼容,使开发者能够轻松地将代码从桌面端转移到微控制器或嵌入式系统。程序可移植性很强,因为不需要考虑底层驱动,所以程序移植变得轻松和容易。</p> +</li> +</ul> +<h2 id="开发环境">开发环境 +</h2><ul> +<li>VScode</li> +<li>Keil(v5.38.0.0)</li> +<li>RT-Thread MicroPython IDE(VScode插件搜索)</li> +<li><a class="link" href="https://github.com/RT-Thread/env-windows/tree/v1.3.5" target="_blank" rel="noopener" +>ENV v1.4.0(可点击链接下载)</a></li> +</ul> +<h2 id="初步移植">初步移植 +</h2><p>首先从RT-Thread官方仓库克隆master分支的仓库到本地</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061052497.png" +loading="lazy" +alt="image-20230206105228123" +></p> +<p>来到该目录:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk</code>,鼠标右键打开ENV工具,首先打开命令行菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>使能添加<code>Micropython软件包</code>:<code>RT-Thread Online Packages---&gt;launage packages---&gt;Micropython</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061100977.png" +loading="lazy" +alt="image-20230206110054882" +></p> +<p><code>Heap size</code>修改为<code>20480</code>(初次分配20K,后续用户可根据需求修改),同时版本选择最新版(这里由于我选择版本时没有注意到最下方的latest版本,但是经测试并于多出的报错问题,相关的报错也可参考该文章)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061103056.png" +loading="lazy" +alt="image-20230206110338978" +></p> +<p>进入<code>Hardware Module</code>,使能<code>machine uart</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061107994.png" +loading="lazy" +alt="image-20230206110701904" +></p> +<p>同时我们回到主菜单界面,进入<code>Hardware Drives config---&gt;on-chip Peripheral Drivers</code>,使能UART0和UART2</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061109036.png" +loading="lazy" +alt="image-20230206110948958" +></p> +<p>由于后续需要在main线程中启动Micropython运行时环境,需要增大main线程的栈大小,这里我们选择栈大小修改为8k:回到主界面<code>RT-Thread Components---&gt;set main thread stack size</code>修改为8192</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061151008.png" +loading="lazy" +alt="image-20230206115128667" +></p> +<p>保存退出,并使用命令下载软件包:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061153317.png" +loading="lazy" +alt="image-20230206115308233" +></p> +<p>使用ENV生成MDK工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061155767.png" +loading="lazy" +alt="image-20230206115527689" +></p> +<h2 id="bug修复">BUG修复 +</h2><p>双击打开<code>project.uvprojx</code>,进行编译</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061157814.png" +loading="lazy" +alt="image-20230206115702684" +></p> +<p>这里由于我们的keil工程为AC6版本(如果您的编译器版本为AC5,应该不需要修改,仅猜测),需要将软件包进行修改:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\SConscript</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061204757.png" +loading="lazy" +alt="image-20230206120429651" +></p> +<p>切记此时需要回到bsp目录下,重新使用ENV工具生成MDK文件,然后再回到keil重新编译工程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译错误大大减少,只剩下三个错误:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212323.png" +loading="lazy" +alt="image-20230206120743700" +></p> +<p>第一个错误需要在菜单中使能<code>Support legacy version for compatibility</code>(目前该问题以推送至官方仓库,已被修复此问题),并重新使用ENV生成MDK工程文件</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061111567.png" +loading="lazy" +alt="image-20230206111143483" +></p> +<p>重新编译继续有报错,这里我们找不到该函数的定义,先在头文件中进行外部声明</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061212175.png" +loading="lazy" +alt="image-20230206121231129" +></p> +<p>找到头文件所在位置:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\micropython-v1.13.0\port\mpgetcharport.h</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061215795.png" +loading="lazy" +alt="image-20230206121521727" +></p> +<p>此时就剩下最后一个错误啦,这里报错是说这个宏没有定义,通过翻阅RT-Thread库函数,确定该宏是文件系统的一个宏,且定义为整型3,具体作用可查看此<a class="link" href="https://github.com/RT-Thread/rt-thread/pull/2100" target="_blank" rel="noopener" +>PR</a>,所以解决该问题就是重新定义一下<code>DFS_FD_OFFSET</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061216368.png" +loading="lazy" +alt="image-20230206121656320" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061220316.png" +loading="lazy" +alt="image-20230206122027240" +></p> +<p>想不到编译之后居然还有一个错误,这里参考这位开发者的<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6657" target="_blank" rel="noopener" +>issue</a>,将<code>list_mem();</code>注释(此处可能是个官方BUG,后续尝试修复)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061221642.png" +loading="lazy" +alt="image-20230206122146590" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061227108.png" +loading="lazy" +alt="image-20230206122748054" +></p> +<p>最后发现,终于没有错误啦!!!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061228418.png" +loading="lazy" +alt="image-20230206122817350" +></p> +<h2 id="rt-thread-micropython环境搭建">RT-Thread Micropython环境搭建 +</h2><p>VScode扩展搜索下载RT-Thread Micropython</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061236343.png" +loading="lazy" +alt="image-20230206123632247" +></p> +<h4 id="创建工程">创建工程 +</h4><p>vscode下方导航栏点击<code>创建Micropython工程</code>,创建一个新的MicroPython工程,并选择工程存放路径</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061519616.png" +loading="lazy" +alt="image-20230206151916502" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061521140.png" +loading="lazy" +alt="image-20230206152143031" +></p> +<h4 id="上电测试micropython">上电测试Micropython +</h4><p>点击下方工具栏连接开发板,打开串口设备后点击复位,此时出现RT-Thread官方LOGO</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061523214.png" +loading="lazy" +alt="image-20230206152315131" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061524180.png" +loading="lazy" +></p> +<h4 id="测试示例">测试示例 +</h4><p>LPC55S69也成功移植了RT-Thread的FINSH组件,点击TAB键可查看Finsh控制台命令,我们可以看到有一个python命令行</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061541861.png" +loading="lazy" +alt="image-20230206154101713" +></p> +<h2 id="micropython测试">Micropython测试 +</h2><p>Finsh控制台输入python,转到python控制台,同时还支持<code>quit()</code>、<code>exit()</code>命令退回Finsh控制台</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061543769.png" +loading="lazy" +alt="image-20230206154310678" +></p> +<p>简单测试下micropython,下面使用python命令运行脚本时给了一个提示说未使能uos module</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061606460.png" +loading="lazy" +alt="image-20230206160622977" +></p> +<p>打开图形化菜单进入该路径下:<code>RT-Thread online packages--&gt;launage packages---&gt;system module</code>,使能<code>uos:basic 'operating system' services </code></p> +<p>同时更新软件包,并使用env工具重新生成MDK,再进行编译下载,成功解决问题!</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302061627396.png" +loading="lazy" +alt="image-20230206162718225" +></p> +<h2 id="结语">结语 +</h2><p>搭建好Micropython后,那么就可以自由发挥才能去创作自己的作品啦!</p> +<h2 id="联系">联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul>瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/Mon, 22 Aug 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/<img src="https://kurisaw.github.io/p/%E7%91%9E%E8%90%A8ra6m4%E5%BC%80%E5%8F%91%E6%9D%BF%E5%9C%A8rt-thread%E4%B8%AD%E4%BD%BF%E7%94%A8segger_rtt%E8%BD%AF%E4%BB%B6%E5%8C%85/cover.jpg" alt="Featured image of post 瑞萨RA6M4开发板在RT-Thread中使用segger_rtt软件包" /><h4 id="一创建工程选择segger_rtt软件包">一、创建工程,选择SEGGER_RTT软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/015bb29dd26648570d03e65cd419f972.png" +loading="lazy" +alt="image-20221003133030692" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fb34abd8ec95bf35f09fb3bcde1f5d1d.png" +loading="lazy" +alt="image-20221003133219108" +></p> +<h4 id="2添加jlinkrtt初始化函数-路径rt-threadsrckservicec-">2、添加jlinkRtt初始化函数[ 路径:/rt-thread/src/kservice.c ] +</h4><p>在<code>rt_console_set_device</code>前调用<code>rt_hw_jlink_rtt_init</code>初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/492ff3b5ab1bf24e62a4380f3d47bf29.png" +loading="lazy" +alt="image-20221003133721333" +></p> +<h4 id="3控制台对接上jlinkrtt">3、控制台对接上jlinkRtt +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rtconfg.h +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// 修改RT_CONSOLE_DEVICE_NAME为空 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/img_convert/a4101391c61fad4add9376b4ebcd71e9.png" +loading="lazy" +alt="image-20221003134935152" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">shell</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="nl">D</span><span class="p">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">components</span><span class="err">\</span><span class="n">finsh</span><span class="err">\</span><span class="n">shell</span><span class="p">.</span><span class="n">c</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 1、首先添加以下头文件 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;SEGGER_RTT_Conf.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 2、修改finsh_getchar */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">finsh_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_DEVICE +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">char</span> <span class="n">ch</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef RT_USING_POSIX_STDIO +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span><span class="p">(</span><span class="nf">read</span><span class="p">(</span><span class="n">STDIN_FILENO</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="cm">/* EOF */</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">rt_device_t</span> <span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">RT_ASSERT</span><span class="p">(</span><span class="n">shell</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="nf">rt_device_read</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ch</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">rx_sem</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span> <span class="o">!=</span> <span class="n">device</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">device</span> <span class="o">=</span> <span class="n">shell</span><span class="o">-&gt;</span><span class="n">device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">device</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ch</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_POSIX_STDIO */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">extern</span> <span class="kt">char</span> <span class="nf">rt_hw_console_getchar</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">rt_hw_console_getchar</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* RT_USING_DEVICE */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">[</span> <span class="err">路径</span><span class="o">:</span><span class="err">\</span><span class="n">rt</span><span class="o">-</span><span class="kr">thread</span><span class="err">\</span><span class="n">src</span><span class="err">\</span><span class="n">kservice</span><span class="p">.</span><span class="n">c</span> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="c1">// 另外我们还需要完成对控制台字符读取的对接,修改rt_hw_console_output +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">RT_WEAK</span> <span class="kt">void</span> <span class="nf">rt_hw_console_output</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* empty console output */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">str</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="sc">&#39;\n&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SEGGER_RTT_printf</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s">&#34;%s&#34;</span><span class="p">,</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">RTM_EXPORT</span><span class="p">(</span><span class="n">rt_hw_console_output</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4实验效果">4、实验效果 +</h4><p>首先确保已经下载好<code>J-Link RTT Viewer</code>,直接去<a class="link" href="https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/" target="_blank" rel="noopener" +>官网</a>下载最新版本即可</p> +<p>然后编译和下载工程,注意下载方式为<code>J-Link</code></p> +<p>双击打开rtthread.map[ 路径: /Debug/rtthread.map ]文件,查看<code>_SEGGER_RTT</code>变量地址(全局搜索即可,找到.bss._SEGGER_RTT)</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/608cb3d791c683d7886a92eef5ae848f.png" +loading="lazy" +alt="image-20221003140449806" +></p> +<p>打开<code>J-Link RTT Viewer</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5e3d4a57e4a6b55dd62f61b5d6577105.png" +loading="lazy" +alt="image-20221003140736161" +></p> +<p>此时就可以正常使用segger_rtt了!</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/d09d8a0f28e2c45542199eb982dfed6e.png" +loading="lazy" +alt="image-20221003140911791" +></p>CPK-RA6M4智慧门禁系统教学https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/Sun, 24 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadcpk-ra6m4%E6%99%BA%E6%85%A7%E9%97%A8%E7%A6%81%E7%B3%BB%E7%BB%9F%E6%95%99%E5%AD%A6/cover.jpg" alt="Featured image of post CPK-RA6M4智慧门禁系统教学" /><p><img src="https://img-blog.csdnimg.cn/img_convert/b98bb037592975e68632b30a8e0845f6.png" +loading="lazy" +alt="image-20220804171524901" +></p> +<h2 id="1项目介绍">1、项目介绍 +</h2><p>本次项目主控为CPK-RA6M4开发板,是瑞萨RA6高性能系列的一款基于Arm架构的开发板,而RA产品家族也是提供了一套成熟的工具生态链来帮助开发者更好的进行产品的研发。本次我们使用瑞萨FSP(灵活配置软件包)结合RT-Thread Studio工具进行项目的研发。</p> +<p>下面来说说本次项目的功能:主要就是通过四大模块结合RT-Thread内核机制,开发出一款具有人员签到打卡、温湿度读取,OLED显示以及云端数据上报这四大功能。</p> +<h2 id="2前期准备">2、前期准备 +</h2><p>开发工具:</p> +<ul> +<li>RT-Thread Studio</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/a95d6ef5c3224144b554bcb416691bcf.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>RT-Thread Studio是一套一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。</p> +<p>RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。</p> +<p>下载链接:<a class="link" href="https://www.rt-thread.org/page/download.html#studio" target="_blank" rel="noopener" +>RT-Thread Studio 下载</a></p> +<ul> +<li>瑞萨FSP(灵活配置软件包)</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/fbdf24dd4b66b39b2f108f558ecf4617.png" +loading="lazy" +alt="Flexible Software Package (FSP)" +></p> +<p>瑞萨电子灵活配置软件包 (FSP) 是一款增强型软件包,旨在为使用瑞萨电子 RA 系列 ARM 微控制器的嵌入式系统设计提供简单易用且可扩展的高质量软件。</p> +<p>下载链接:<a class="link" href="https://github.com/renesas/fsp/releases/tag/v3.5.0" target="_blank" rel="noopener" +>瑞萨FSP v3.5.0</a></p> +<p>模块:</p> +<ul> +<li>AHT10</li> +<li>ESP8266</li> +<li>RC522及读卡标签</li> +<li>ssd1306 OLED显示屏</li> +</ul> +<h2 id="3模块介绍及使用">3、模块介绍及使用 +</h2><h4 id="31-aht10">3.1 AHT10 +</h4><h6 id="311底层i2c通信协议简介">3.1.1底层I2C通信协议简介 +</h6><p>I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。</p> +<p>而I2C通信的读写数据是通过等待从机的应答信号(ACK)。</p> +<p>也就是说,当配置方向为“写数据”时,主机每发送完一个字节数据,都要等待从机的应答信号,而当数据传输结束时,主机向从机发送一个停止传输信号,表示不再传输数据;当配置方向为“读数据”时,从机每发送完一个数据,都需要等待主机的应答信号,当主机希望停止接收数据时,会向从机发送一个非应答信号(NACK),从机就不再向主机继续发送数据。</p> +<p>这里需要注意的是,I2C通讯常用的是复合格式,该传输过程中有两次起始信号。在第一次传输中,主机通过slave_address找到从设备后会发送一段数据(通常表示从设备内部的寄存器或存储器系统);而在第二次的传输中,对该地址的内容进行读写,也就是说,第一次通讯时告诉从机读写地址,第二次通讯才是读写的实际内容。</p> +<p>当 SCL 线是高电平时, SDA 线从高电平向低电平切换,这时候代表通讯的起始;当SCL 是高电平时, SDA线由低电平向高电平切换,这代表通讯的结束。</p> +<p>简单来说,就是I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。</p> +<h6 id="312-sensor框架的使用">3.1.2 sensor框架的使用 +</h6><p>在RT-Thread中,我们需要了解sensor设备的作用,是为上层提供统一的操作接口,提高上层代码的可重用性。</p> +<p>掌握sensor框架的使用,需要了解一下API的调用:</p> +<table> +<thead> +<tr> +<th style="text-align:center"><strong>函数</strong></th> +<th style="text-align:center"><strong>描述</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">rt_device_find()</td> +<td style="text-align:center">根据传感器设备设备名称查找设备获取设备句柄</td> +</tr> +<tr> +<td style="text-align:center">rt_device_open()</td> +<td style="text-align:center">打开传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_read()</td> +<td style="text-align:center">读取数据</td> +</tr> +<tr> +<td style="text-align:center">rt_device_control()</td> +<td style="text-align:center">控制传感器设备</td> +</tr> +<tr> +<td style="text-align:center">rt_device_set_rx_indicate()</td> +<td style="text-align:center">设置接收回调函数</td> +</tr> +<tr> +<td style="text-align:center">rt_device_close()</td> +<td style="text-align:center">关闭传感器设备</td> +</tr> +</tbody> +</table> +<h6 id="313-aht10对接到sensor框架">3.1.3 AHT10对接到sensor框架 +</h6><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">SCL</td> +<td style="text-align:center">P512</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P511</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>然后我们打开settings,在硬件部分使能I2C1(芯片设备驱动-&gt;Enable I2C BUS-&gt;使能I2C1),同时可以检查下组件部分I2C设备驱动程序是否使能</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/f301db2fd8e1988f2ca4e311c5d973cf.png" +loading="lazy" +alt="image-20220805110607476" +></p> +<p>然后使用下面的程序完成模块初始化工作</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;sensor_asair_aht10.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define AHT10_I2C_BUS &#34;i2c1&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 模块初始化工作 */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_aht10_port</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_sensor_config</span> <span class="n">cfg</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">dev_name</span> <span class="o">=</span> <span class="n">AHT10_I2C_BUS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">intf</span><span class="p">.</span><span class="n">user_data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">AHT10_I2C_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_init</span><span class="p">(</span><span class="s">&#34;aht10&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_ENV_EXPORT</span><span class="p">(</span><span class="n">rt_hw_aht10_port</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>AHT10温湿度数据读取</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="c1">// AHT10设备读取数值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">aht10_device_t</span> <span class="n">dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_hw_aht10_port</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">dev</span> <span class="o">=</span> <span class="nf">aht10_init</span><span class="p">(</span><span class="n">AHT10_I2C_BUS</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes failure&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34; The sensor initializes ok!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read humidity 采集湿度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="nf">aht10_read_humidity</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read temperature 采集温度 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="nf">aht10_read_temperature</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="32-esp8266">3.2 ESP8266 +</h4><h6 id="321-底层uart简介">3.2.1 底层uart简介 +</h6><p>UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。</p> +<p>UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。</p> +<ul> +<li>串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。</li> +<li>异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。也就是说两个uart设备之间通信的时候不需要时钟线,但是需要在两个uart设备上指定相同的传输速率,以及空闲位、起始位、校验位、结束位,也就是遵循相同的协议。</li> +<li>数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5fdffba894c94d48a14c4f64a9992b93.jpeg" +loading="lazy" +alt="查看源图像" +></p> +<p>空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。</p> +<p>起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。</p> +<p>数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位,剩下的1位二进制为0),扩展BCD码(8位)。<code>先发送最低位,最后发送最高位</code>,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。</p> +<h6 id="322-mqtt通讯协议介绍">3.2.2 MQTT通讯协议介绍 +</h6><p>MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quot;轻量级&quot;通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。</p> +<p>其优点就是利用极少的代码和有限的带框,为物联网设备远程通讯提供消息传输服务, 相比于HTTP协议在互联网上的客户端请求,服务端应答模式,MQTT的发布订阅模式在物联网设备上更适用。</p> +<p>实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。</p> +<p><img src="https://img-blog.csdnimg.cn/a665ee8ebb4d427bbfa4c8a7ec013913.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h6 id="323-at组件">3.2.3 AT组件 +</h6><p>AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式。 其基本结构如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/1eb3c2cd78584efa85656a2cdd8daa8f.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>由上图可知,AT的使用需要AT Client和AT Server这两部分共同完成,AT Client通过AT命令向Server发送请求,等待Server的响应,并对响应的数据或主动发送给Client的数据(URC数据)进行解析处理,并获取相关信息。</p> +<h6 id="324-mqtt协议及at组件在rt-thread中的使用">3.2.4 MQTT协议及AT组件在RT-Thread中的使用 +</h6><p><strong>RT-Thread Settings设置</strong></p> +<p>添加AT Device及OneNET软件包</p> +<p>AT Device配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf1c743b728c70c2764a3db1d368039c.png" +loading="lazy" +alt="image-20220805122341394" +></p> +<p>OneNET配置:</p> +<p>首先我们需要前往ONENET官网进行产品创建及设备绑定,没有onenet账号的可以去注册一个。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/b40025d68d9bd0f32ff6efa3b74ff12d.png" +loading="lazy" +alt="image-20220805122741348" +> +<img src="https://img-blog.csdnimg.cn/img_convert/c7c17c8d743dca043a098be627baf93c.png" +loading="lazy" +alt="image-20220805122836636" +></p> +<p>然后将创建的信息填写到settings中</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9588bef3c3bf99d27bdc3cbd56394ece.png" +loading="lazy" +alt="image-20220805123248475" +></p> +<p>在组件中使能AT命令</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ad6b80e0d34df83a213dcdbf85d4416b.png" +loading="lazy" +alt="image-20220805123407687" +></p> +<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">TX</td> +<td style="text-align:center">P100</td> +</tr> +<tr> +<td style="text-align:center">RX</td> +<td style="text-align:center">P101</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">5V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p><strong>FSP配置</strong></p> +<p>由于RT-Thread提供了有限的驱动配置,所以需要我们使用瑞萨FSP进行相关的配置</p> +<p>首先点击<code>RA Smart Configurator</code>,记住这里使用的FSP版本为<code>v3.5.0</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/7710c9a62ad3a4486362f9d4bf92869f.png" +loading="lazy" +alt="image-20220805152204348" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/2cb89487678dcf16bf3c784851a42091.png" +loading="lazy" +alt="image-20220805153017364" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/bf0866f3d50eae91f43aee142ef06966.png" +loading="lazy" +alt="image-20220805153317144" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/58fb0f18f54f0eaf49598c6c20f67b62.png" +loading="lazy" +alt="image-20220805153416015" +></p> +<p>完成上述操作后保存并编译,注意这里由于RT-Thread版本问题,可能出现<code>#include &lt;dfs_posix.h&gt;</code>未参与编译以及还有其他一些问题,可以参考这一issue<a class="link" href="https://github.com/RT-Thread/rt-thread/issues/6188" target="_blank" rel="noopener" +>[CPK-RA6M4] onenet上云报错&lt;RT-Thread 的版本为 4.1.0 及以上&gt;</a></p> +<p>现在可以下载到开发板了,由于我们使用的AT例程中是默认初始化运行,所以在上电后就会自动连接WIFI了。</p> +<p>然后就是数据上云,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;temperature&#34;</span><span class="p">,</span><span class="n">temperature</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_delay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">onenet_mqtt_upload_digit</span><span class="p">(</span><span class="s">&#34;humidity&#34;</span><span class="p">,</span><span class="n">humidity</span> <span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;upload has an error, stop uploading&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;humidity : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们创建了两个数据流,分别是温度以及湿度。在AHT10读取温湿度之后,就可以进行数据的上报了,然后可以在onenet官网不断看到数据的上报了。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/096cd5faec78062ac227adcc12f08f05.png" +loading="lazy" +alt="image-20220805145942277" +></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/67bd30c613f9a819cc2b7abddb58a5bc.png" +loading="lazy" +alt="image-20220805145958887" +></p> +<h4 id="33-rc522">3.3 RC522 +</h4><h6 id="331-底层spi协议简介">3.3.1 底层SPI协议简介 +</h6><p>SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/9d4277d0aba7be84c59b68efb9402995.png" +loading="lazy" +alt="SPI 主设备和从设备的连接方式" +></p> +<ul> +<li>MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。</li> +<li>MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。</li> +<li>SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。</li> +<li>CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。</li> +</ul> +<p>整体的传输大概可以分为以下几个过程:</p> +<p>(1)主机先将<code>NSS</code>信号拉低,这样保证开始接收数据;</p> +<p>(2)当<strong>接收端</strong>检测到时钟的边沿信号时,它将立即读取<strong>数据线</strong>上的信号,这样就得到了一位数据(1<code>bit</code>;由于时钟是随数据一起发送的,因此指定<strong>数据的传输速度并不重要</strong>,尽管设备将具有可以运行的最高速度。</p> +<p>(3)<strong>主机</strong>发送到<strong>从机</strong>时:主机产生相应的时钟信号,然后数据<strong>一位一位</strong>地将从<code>MOSI</code>信号线上进行发送到从机;</p> +<p>(4)<strong>主机</strong>接收<strong>从机</strong>数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过<code>MISO</code>信号线发送;</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/3c32f25bed1d6e44c840608e4e352fc4.png" +loading="lazy" +alt="查看源图像" +></p> +<h6 id="332-rc522读卡机制说明">3.3.2 RC522读卡机制说明 +</h6><p>首先来看下RC522与M1卡的通讯流程:</p> +<p><strong>寻卡-&gt;防止卡片冲撞-&gt;选卡-&gt;休眠-&gt;发送0x40(7bit)-&gt;发送0x43-&gt;发送0xa0等4字节-&gt;发送0x00等18字节</strong></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/4c59b975aa9fdccbb19b38b059b87e1a.png" +loading="lazy" +alt="image-20220805154320392" +></p> +<ul> +<li> +<p>复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。</p> +</li> +<li> +<p>防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。</p> +</li> +<li> +<p>选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。</p> +</li> +<li> +<p>三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。</p> +</li> +<li> +<p>对数据块的操作: +读(Read):读一个块的数据; +写(Write):在一个块中写数据; +加(Increment):对数据块中的数值进行加值; +减(Decrement):对数据块中的数值进行减值; +传输(Transfer):将数据寄存器中的内容写入数据块中; +中止(Halt):暂停卡片的工作;</p> +</li> +</ul> +<h6 id="333-rc522在rt-thread的使用">3.3.3 RC522在RT-Thread的使用 +</h6><p>首先打开settings,添加RC522软件包,并在硬件部分使能SPI1</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/ef7c08d20f957c70b67fe63943fec730.png" +loading="lazy" +alt="image-20220805155052783" +></p> +<p>打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/263c237d561d232466249aacb0dd42a4.png" +loading="lazy" +alt="image-20220805155448374" +></p> +<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">MOSI</td> +<td style="text-align:center">P411</td> +</tr> +<tr> +<td style="text-align:center">MISO</td> +<td style="text-align:center">P410</td> +</tr> +<tr> +<td style="text-align:center">SCL</td> +<td style="text-align:center">P412</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P311</td> +</tr> +<tr> +<td style="text-align:center">RST</td> +<td style="text-align:center">P312</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +<tr> +<td style="text-align:center">IRQ</td> +<td style="text-align:center">悬空</td> +</tr> +</tbody> +</table> +<p>代码部分参考RC522sample</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/474416ef76e9523302b9cdd544bbf03b.png" +loading="lazy" +alt="image-20220805155715593" +></p> +<p>SPI初始化配置:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;mfrc522.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_spi_device</span> <span class="n">mfrc522_spi_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">pin</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">rt_hw_spi_cs</span> <span class="n">spi_cs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_hw_spi_rc522_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_err_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Attach Device +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span> <span class="o">=</span> <span class="n">MFRC522_SS_PIN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">spi_cs</span><span class="p">.</span><span class="n">pin</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span> <span class="o">=</span> <span class="nf">rt_spi_bus_attach_device</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">,</span> <span class="n">MFRC522_SPI_BUS_NAME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">spi_cs</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[RC522] Failed to attach device %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">MFRC522_SPI_DEVICE_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// Set device SPI Mode +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="n">rt_spi_configuration</span> <span class="n">cfg</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">data_width</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">RT_SPI_MASTER</span> <span class="o">|</span> <span class="n">RT_SPI_MODE_0</span> <span class="o">|</span> <span class="n">RT_SPI_MSB</span> <span class="o">|</span> <span class="n">RT_SPI_NO_CS</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cfg</span><span class="p">.</span><span class="n">max_hz</span> <span class="o">=</span> <span class="n">MFRC522_SPICLOCK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_spi_configure</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mfrc522_spi_dev</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cfg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cm">/* 导出到自动初始化 */</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_hw_spi_rc522_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>另外需要在完成一下配置,<code>双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/5045a3933b508b5267b5fb9eeec6064b.png" +loading="lazy" +alt="image-20220805155922942" +></p> +<p>打开mfrc522.c,修改配置<code>MFRC522_SS_PIN</code>及<code>MFRC522_RST_PIN</code></p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c61dba211ccb8ece988de9e703dc15cb.png" +loading="lazy" +alt="image-20220805161330936" +></p> +<p>打开rtconfig.h,找到以下两个引脚的定义,修改成如下:</p> +<p>注意:<strong><code>一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置</code></strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define MFRC522_SS_PIN 0x3b +</span></span><span class="line"><span class="cl">#define MFRC522_RST_PIN 0x3c +</span></span></code></pre></td></tr></table> +</div> +</div><p>至此,RC522的相关配置结束</p> +<h4 id="34-ssd1306">3.4 SSD1306 +</h4><h6 id="341-底层i2c通信协议">3.4.1 底层I2C通信协议 +</h6><p>(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)</p> +<h6 id="342-ssd1306在rt-thred的使用">3.4.2 SSD1306在RT-Thred的使用 +</h6><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">SCL</td> +<td style="text-align:center">P400</td> +</tr> +<tr> +<td style="text-align:center">SDA</td> +<td style="text-align:center">P401</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">3.3V</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">GND</td> +</tr> +</tbody> +</table> +<p>RT-Thread Settings配置:</p> +<p>添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/c6b56810a69b472ea12eaa4e8d60008a.png" +loading="lazy" +alt="image-20220805162320450" +></p> +<p>打开rtconfig.h,添加i2c代码,<code>注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码</code>:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SCL_PIN 0x400 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C0_SDA_PIN 0x401 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开drv_soft_i2c.c文件,添加代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define I2C0_BUS_CONFIG \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> { \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .scl = BSP_I2C0_SCL_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .sda = BSP_I2C0_SDA_PIN, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> .bus_name = &#34;i2c0&#34;, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> } +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/04a3d96e15bbde106c73e389eca7fe10.png" +loading="lazy" +alt="image-20220805162941069" +></p> +<p>生成配置之后添加用户代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;ssd1306.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_init</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">25</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Hello RT-Thread!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_APP_EXPORT</span><span class="p">(</span><span class="n">oled_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实时时钟显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Now Time&#34;</span><span class="p">,</span> <span class="n">Font_16x26</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">40</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;:&#34;</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="n">Font_11x18</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>温湿度数据显示代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"> <span class="nf">ssd1306_Fill</span><span class="p">(</span><span class="n">White</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="s">&#34;Humi_Temp_Detection!&#34;</span><span class="p">,</span> <span class="n">Font_7x10</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Temperature: %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Temperature_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">),</span> <span class="s">&#34;Humidity:%d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_SetCursor</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">47</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_WriteString</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">Font_6x8</span><span class="p">,</span> <span class="n">Black</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ssd1306_UpdateScreen</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Humidity_OLED : %d.%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4整体代码框架">4、整体代码框架 +</h2><h4 id="41-多线程任务分配">4.1 多线程任务分配 +</h4><p>本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。</p> +<p>所以共创建四个线程:</p> +<p>(1)RC522_thread:用于RC522读卡</p> +<p>(2)aht10_read_thread:用于aht10读取温湿度数值</p> +<p>(3)onenet_aht10_thread:云端数据上报</p> +<p>(4)oled_thread:OLED显示</p> +<h4 id="42-线程间交互">4.2 线程间交互 +</h4><p>本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。</p> +<h4 id="43-代码整合">4.3 代码整合 +</h4><p><img src="https://img-blog.csdnimg.cn/img_convert/8aed1d64ef9fd8e219744b794b8dd048.png" +loading="lazy" +alt="image-20220802210559475" +></p> +<p>在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。</p> +<p>都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。</p> +<p><img src="https://img-blog.csdnimg.cn/img_convert/36369721fa7745022aab2ad2492dc64f.png" +loading="lazy" +alt="image-20220805171602257" +></p> +<h2 id="5踩坑指南">5、踩坑指南 +</h2><p>其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:</p> +<p>(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为<code>v3.5.0</code></p> +<p>(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。</p> +<p>(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。</p> +<div class="video-wrapper"> +<iframe src="https://player.bilibili.com/player.html?as_wide=1&amp;high_quality=1&amp;page=1.8&bvid=BV1Ld4y1N7eo" +scrolling="no" +frameborder="no" +framespacing="0" +allowfullscreen="true" +> +</iframe> +</div>ART-Pi 网络时钟https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/Fri, 22 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadart-pi-%E7%BD%91%E7%BB%9C%E6%97%B6%E9%92%9F/cover.jpg" alt="Featured image of post ART-Pi 网络时钟" /><h2 id="玩转rt-thread自制网络时钟">《玩转RT-Thread》自制网络时钟 +</h2><hr> +<p>@[toc]</p> +<h2 id="一准备工作">一、准备工作 +</h2><ul> +<li> +<p>开发平台:RT-Thread Studio</p> +</li> +<li> +<p>开发板:ART-PI</p> +</li> +<li> +<p>主控芯片:STM32H750</p> +</li> +<li> +<p>温湿度传感器:SHT30</p> +</li> +<li> +<p>显示模组:0.96’OLED(SSD1306)</p> +</li> +<li> +<p>串口调试助手:SecureCRT</p> +</li> +</ul> +<p>注意:这里由于ART-PI开发板自带WiFi模组,可直接使能。如果使用其他开发板,可考虑使用ESP8266通信模块。</p> +<h2 id="二新建rt-thread-项目">二、新建RT-Thread 项目 +</h2><p><img src="https://img-blog.csdnimg.cn/dfeff108ee0241919514065992e79ef8.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/9f49c13343914adf8d92f12a1ebf832e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="三获取温湿度数据">三、获取温湿度数据 +</h2><h4 id="1双击打开左边导航栏的rt-thread-setting">1、双击打开左边导航栏的RT-Thread Setting +</h4><p><img src="https://img-blog.csdnimg.cn/096e053c2ec545a9950c86dcb1e12d9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2使能软件模拟i2c单击点亮即可">2、使能软件模拟i2c(单击点亮即可) +</h4><p><img src="https://img-blog.csdnimg.cn/6bb6a362155641c0b0b6fa0953c60e45.png" +loading="lazy" +></p> +<h4 id="3配置i2c及相关引脚">3、配置i2c及相关引脚 +</h4><p><code>这里的i2c引脚配置依自己开发板而定,配置完成后CTRL+S保存配置</code></p> +<p><img src="https://img-blog.csdnimg.cn/ae8aaaa39cf04296809e01ccef73d980.png" +loading="lazy" +></p> +<h4 id="4添加sht3x软件包">4、添加SHT3X软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/d480f380b622466c9c38ae5129550067.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置,点击编译并下载</code></p> +<p>具体RT-Thread Studio的一般使用可参照<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124079730?spm=1001.2014.3001.5502" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)</a></p> +<p><code>此时打开串口工具,可以看到前面配置的i2c1和i2c3已经注册成功</code></p> +<p><img src="https://img-blog.csdnimg.cn/04803141590e474bbe767242a8258ed5.png" +loading="lazy" +></p> +<p>此时在串口输入help,可以看出有一个sht3x配置</p> +<p><img src="https://img-blog.csdnimg.cn/bb9d35af5d19463282a1bd8400e90364.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">输入: +</span></span><span class="line"><span class="cl">sht3x probe i2c3 pd +</span></span><span class="line"><span class="cl">sht3x read(读取温湿度信息) +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="四获取ntp时间">四、获取NTP时间 +</h2><h4 id="1使能选择wifi框架">1、使能选择WiFi框架 +</h4><p><img src="https://img-blog.csdnimg.cn/fac0022dff324acc9aa4a94e85407e69.png" +loading="lazy" +></p> +<h4 id="2使能ap6212库">2、使能AP6212库 +</h4><p><img src="https://img-blog.csdnimg.cn/97afeb11678140b2a5acbea44bc8937f.png" +loading="lazy" +></p> +<h4 id="3添加easyflash和netutils软件包">3、添加easyflash和netutils软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/08cda56d446541358d2b5038545ca284.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>鼠标右键netutils打开配置项</code></p> +<p><img src="https://img-blog.csdnimg.cn/cd98d8f9bb0f4f15941c4617c32b7aa3.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><code>使能NTP (网络时间协议)客户端 </code></p> +<p><img src="https://img-blog.csdnimg.cn/7fe0c1a627d94d1dba87dbcf4918d127.png" +loading="lazy" +></p> +<p><code>使能软件模拟RTC</code></p> +<p><img src="https://img-blog.csdnimg.cn/f2ac26826c0a463bb1124804fcc7c563.png" +loading="lazy" +></p> +<p><code>CTRL+S保存配置</code></p> +<p><code>修改配置</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cassandra" data-lang="cassandra"><span class="line"><span class="cl"><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="err">打开电脑中项目所在的路径</span><span class="o">-</span><span class="n">workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">packages</span><span class="o">-</span><span class="n">EasyFlash</span><span class="o">-</span><span class="n">v4</span><span class="err">.1.0</span><span class="o">-</span><span class="n">port</span><span class="err">,将</span><span class="n">port目录下的ef_fal_port</span><span class="p">.</span><span class="n">c文件复制到workpace</span><span class="o">-</span><span class="err">项目名称</span><span class="o">-</span><span class="n">board</span><span class="o">-</span><span class="n">port中</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="err">修改</span><span class="n">port中宏定义FAL_EF_PART_NAME</span><span class="w"> </span><span class="err">中的名字</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">#</span><span class="n">define</span><span class="w"> </span><span class="n">FAL_EF_PART_NAME</span><span class="w"> </span><span class="s">&#34;easyflash&#34;</span><span class="w"> </span><span class="c1">//修改后的宏定义 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>此时再编译并下载到开发板中</code></p> +<h4 id="4连接wifi">4、连接WiFi +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">wifi</span> <span class="n">scan</span> <span class="c1">//搜索wifi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">wifi</span> <span class="n">join</span> <span class="p">[</span><span class="n">SSID</span><span class="p">]</span> <span class="p">[</span><span class="n">PASSWORD</span><span class="p">]</span> <span class="c1">//连接WiFi +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="nl">SSID</span><span class="p">:</span><span class="n">WiFi名称</span> +</span></span><span class="line"><span class="cl"><span class="n">PASSWORD</span><span class="err">:</span><span class="n">WiFi密码</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5设置开机自连接wifi">5、设置开机自连接WiFi +</h4><p><code>(1)在board/port 目录下创建wifi_config.c文件来实现wifi上电自动连接 代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_WIFI +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_mgnt.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_cfg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;wlan_prot.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;easyflash.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;fal.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#if (EF_SW_VERSION_NUM &lt; 0x40000) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">base64_table</span><span class="p">[</span><span class="mi">65</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="mi">256</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3E</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x3F</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x34</span><span class="p">,</span> <span class="mh">0x35</span><span class="p">,</span> <span class="mh">0x36</span><span class="p">,</span> <span class="mh">0x37</span><span class="p">,</span> <span class="mh">0x38</span><span class="p">,</span> <span class="mh">0x39</span><span class="p">,</span> <span class="mh">0x3A</span><span class="p">,</span> <span class="mh">0x3B</span><span class="p">,</span> <span class="mh">0x3C</span><span class="p">,</span> <span class="mh">0x3D</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0A</span><span class="p">,</span> <span class="mh">0x0B</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x0D</span><span class="p">,</span> <span class="mh">0x0E</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x10</span><span class="p">,</span> <span class="mh">0x11</span><span class="p">,</span> <span class="mh">0x12</span><span class="p">,</span> <span class="mh">0x13</span><span class="p">,</span> <span class="mh">0x14</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x16</span><span class="p">,</span> <span class="mh">0x17</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="mh">0x19</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0x1B</span><span class="p">,</span> <span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x1D</span><span class="p">,</span> <span class="mh">0x1E</span><span class="p">,</span> <span class="mh">0x1F</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="mh">0x21</span><span class="p">,</span> <span class="mh">0x22</span><span class="p">,</span> <span class="mh">0x23</span><span class="p">,</span> <span class="mh">0x24</span><span class="p">,</span> <span class="mh">0x25</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0x27</span><span class="p">,</span> <span class="mh">0x28</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x29</span><span class="p">,</span> <span class="mh">0x2A</span><span class="p">,</span> <span class="mh">0x2B</span><span class="p">,</span> <span class="mh">0x2C</span><span class="p">,</span> <span class="mh">0x2D</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x2F</span><span class="p">,</span> <span class="mh">0x30</span><span class="p">,</span> <span class="mh">0x31</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0x33</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">src</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pos</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">end</span><span class="p">,</span> <span class="o">*</span><span class="n">in</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">olen</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">=</span> <span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="cm">/* 3-byte blocks to 4-byte */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span> <span class="o">+=</span> <span class="n">olen</span> <span class="o">/</span> <span class="mi">72</span><span class="p">;</span> <span class="cm">/* line feeds */</span> +</span></span><span class="line"><span class="cl"> <span class="n">olen</span><span class="o">++</span><span class="p">;</span> <span class="cm">/* nul termination */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">end</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span> <span class="o">+</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">pos</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">6</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x3f</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">in</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">in</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[((</span><span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">|</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)];</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="n">base64_table</span><span class="p">[(</span><span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;=&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">pos</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * return: length, 0 is error. +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int</span> <span class="n">input_length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">decoded_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">input_length</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">out_len</span> <span class="o">=</span> <span class="n">input_length</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">input_length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span><span class="p">)</span> <span class="n">out_len</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">input_length</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_a</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_b</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_c</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">sextet_d</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;=&#39;</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">&amp;</span> <span class="n">i</span><span class="o">++</span> <span class="o">:</span> <span class="n">base64_decode_table</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">triple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sextet_a</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_b</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_c</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="o">+</span> <span class="p">(</span><span class="n">sextet_d</span> <span class="o">&lt;&lt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">6</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">out_len</span><span class="p">)</span> <span class="n">decoded_data</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">triple</span> <span class="o">&gt;&gt;</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">out_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_info</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_info</span> <span class="o">!=</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_decode</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">,</span> <span class="nf">rt_strlen</span><span class="p">(</span><span class="n">wlan_cfg_info</span><span class="p">),</span> <span class="n">buff</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">wlan_cfg_len</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">wlan_cfg_len</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">wlan_cfg_len</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">base64_buf</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">base64_buf</span> <span class="o">=</span> <span class="nf">rt_malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span> <span class="cm">/* 3-byte blocks to 4-byte, and the end. */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">base64_buf</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">wlan_cfg_len</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="n">wlan_cfg_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">str_base64_encode_len</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">base64_buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">read_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">get_len</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">saved_len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_get_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">saved_len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">saved_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">write_cfg</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buff</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config lengths to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_len&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">len</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the wlan config information to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env_blob</span><span class="p">(</span><span class="s">&#34;wlan_cfg_info&#34;</span><span class="p">,</span> <span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* (EF_SW_VERSION_NUM &lt; 0x40000) */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">rt_wlan_cfg_ops</span> <span class="n">ops</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_cfg</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">get_len</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_cfg</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="nf">easyflash_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_set_ops</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ops</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_cfg_cache_refresh</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在main.c中添加自动连接函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define LED_PIN GET_PIN(I, 8) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* init Wi-Fi auto connect feature */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* enable auto reconnect on WLAN device */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>编译并下载,此时开发板就能够从flash中自动读取上次连接数据并自动连接WiFi了。</code></p> +<h2 id="五oled屏显示温湿度和实时时间信息">五、OLED屏显示温湿度和实时时间信息 +</h2><h4 id="1添加u8g2软件包">1、添加u8g2软件包 +</h4><p><img src="https://img-blog.csdnimg.cn/9aa5ecc3b3484b14b1c57ef4c75aae73.png" +loading="lazy" +></p> +<h4 id="2编写oled_display显示线程">2、编写oled_display显示线程 +</h4><p><code>(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。</code></p> +<p><code>代码如下:</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rthw.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;U8g2lib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;drv_soft_i2c.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sht3x.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="n">sht3x_device_t</span> <span class="nf">sht3x_init</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">i2c_bus_name</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">sht3x_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="nf">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device_t</span> <span class="n">dev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define OLED_I2C_PIN_SCL 24 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define OLED_I2C_PIN_SDA 25 </span><span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">U8G2_SSD1306_128X64_NONAME_F_SW_I2C</span> <span class="nf">u8g2</span><span class="p">(</span><span class="n">U8G2_R0</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* clock=*/</span> <span class="n">OLED_I2C_PIN_SCL</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* data=*/</span> <span class="n">OLED_I2C_PIN_SDA</span><span class="p">,</span>\ +</span></span><span class="line"><span class="cl"> <span class="cm">/* reset=*/</span> <span class="n">U8X8_PIN_NONE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define SUN 0 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SUN_CLOUD 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define CLOUD 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RAIN 3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define THUNDER 4 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeatherSymbol</span><span class="p">(</span><span class="n">u8g2_uint_t</span> <span class="n">x</span><span class="p">,</span> <span class="n">u8g2_uint_t</span> <span class="n">y</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// fonts used: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_embedded_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// u8g2_font_open_iconic_weather_6x_t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">symbol</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">69</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">SUN_CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">65</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">CLOUD</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">64</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">RAIN</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_weather_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nl">THUNDER</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_open_iconic_embedded_6x_t</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawGlyph</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">67</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawWeather</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">degree</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">degree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">drawHumidity</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">symbol</span><span class="p">,</span> <span class="kt">int</span> <span class="n">humidity</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeatherSymbol</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="n">symbol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">55</span><span class="p">,</span> <span class="mi">63</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;%&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso32_tf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">48</span><span class="o">+</span><span class="mi">3</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">&#34;Hi~&#34;</span><span class="p">);</span> <span class="c1">// requires enableUTF8Print() +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_6x13_tr</span><span class="p">);</span> <span class="c1">// choose a suitable font +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s">&#34;By Mculover666&#34;</span><span class="p">);</span> <span class="c1">// write something to the internal memory +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device_t</span> <span class="n">sht3x_device</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sht3x_device</span> <span class="o">=</span> <span class="n">sht3x_init</span><span class="p">(</span><span class="s">&#34;i2c3&#34;</span><span class="p">,</span> <span class="mh">0x44</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">mstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">hstr</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">time_t</span> <span class="n">now</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="nc">tm</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">min</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">hour</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">switch</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">0</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">(</span><span class="n">RT_NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">=</span><span class="n">gmtime</span><span class="p">((</span><span class="k">const</span> <span class="n">time_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">now</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">hour</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_hour</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">min</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">tm_min</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">mstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">min</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">sprintf</span><span class="p">(</span><span class="n">hstr</span><span class="p">,</span> <span class="s">&#34;%02d&#34;</span><span class="p">,</span> <span class="n">hour</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">firstPage</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">do</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">setFont</span><span class="p">(</span><span class="n">u8g2_font_logisoso42_tn</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">hstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="s">&#34;:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">drawStr</span><span class="p">(</span><span class="mi">67</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="n">mstr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span> <span class="n">u8g2</span><span class="p">.</span><span class="n">nextPage</span><span class="p">()</span> <span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">1</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawWeather</span><span class="p">(</span><span class="n">SUN</span><span class="p">,</span> <span class="n">temperature</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="mi">2</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">RT_EOK</span> <span class="o">==</span> <span class="n">sht3x_read_singleshot</span><span class="p">(</span><span class="n">sht3x_device</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">sht3x_device</span><span class="o">-&gt;</span><span class="n">humidity</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">clearBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">drawHumidity</span><span class="p">(</span><span class="n">RAIN</span><span class="p">,</span> <span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">u8g2</span><span class="p">.</span><span class="n">sendBuffer</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">5000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">oled_display</span><span class="p">,</span> <span class="n">oled</span> <span class="n">start</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(2)在 applications 文件夹下创建oled_display.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2021, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2022-06-09 ASUS the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define APPLICATIONS_OLED_DISPLAY_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">oled_display</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* APPLICATIONS_OLED_DISPLAY_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>(3)最终的主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2020, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2020-09-02 RT-Thread first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_common.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">void</span> <span class="nf">wlan_autoconnect_init</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_pin_mode</span><span class="p">(</span><span class="n">LED_PIN</span><span class="p">,</span> <span class="n">PIN_MODE_OUTPUT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">wlan_autoconnect_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_wlan_config_autoreconnect</span><span class="p">(</span><span class="n">RT_TRUE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">oled_display</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;stm32h7xx.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">static</span> <span class="kt">int</span> <span class="nf">vtor_config</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Vector Table Relocation in Internal QSPI_FLASH */</span> +</span></span><span class="line"><span class="cl"> <span class="n">SCB</span><span class="o">-&gt;</span><span class="n">VTOR</span> <span class="o">=</span> <span class="n">QSPI_BASE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_BOARD_EXPORT</span><span class="p">(</span><span class="n">vtor_config</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/*-------------------------- I2C CONFIG BEGIN --------------------------*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C1_SCL_PIN 24 </span><span class="c1">// p2 10 PB8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C1_SDA_PIN 25 </span><span class="c1">// p2 7 PB9 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BSP_USING_I2C3 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define BSP_I2C3_SCL_PIN 119 </span><span class="c1">//p1 29 PH7 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define BSP_I2C3_SDA_PIN 120 </span><span class="c1">//p1 28 PH8 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/*-------------------------- UART CONFIG END --------------------------*/</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六实验展示">六、实验展示 +</h2><p><img src="https://img-blog.csdnimg.cn/c0cbf5357ce14d7d963684d4338eee9e.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/d329c18ee11d45a59252f42bb043663b.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/99f00b0cf72b4e20a0697914e7048f97.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="七问题总结">七、问题总结 +</h2><p><code>注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// cpp函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><code>在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。</code></p> +<hr> +<p>这次的分享就到这里,有相关问题的欢迎留言私信!</p>线程间同步 信号量https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/Sun, 17 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%90%8C%E6%AD%A5-%E4%BF%A1%E5%8F%B7%E9%87%8F/cover.jpg" alt="Featured image of post 线程间同步 信号量" /><h2 id="一概述">一、概述: +</h2><blockquote> +<p>多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:</p> +</blockquote> +<p><strong>信号量</strong>(semaphore)、<strong>互斥量</strong>(mutex)、和<strong>事件集</strong>(event)</p> +<h2 id="二信号量">二、信号量 +</h2><h4 id="1简述">1、简述 +</h4><p>信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到<code>同步</code>或<code>互斥</code>的目的。</p> +<p>信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当<code>信号量实例数目为零时</code>,再申请该信号量的线程就会被<code>挂起</code>在该信号量的等待队列上,等待可用的信号量实例(资源)。</p> +<p><img src="https://img-blog.csdnimg.cn/55d38f32e6e84b038d35a27bea1b9074.png" +loading="lazy" +></p> +<h4 id="2信号量结构体">2、信号量结构体 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_ipc_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; 继承自ipc_object类 */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">value</span><span class="p">;</span> <span class="cm">/**&lt; value of semaphore. */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint16_t</span> <span class="n">reserved</span><span class="p">;</span> <span class="cm">/**&lt; reserved field 预留*/</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当线程对资源进行获取时,value值进行减一操作;直到该信号量被释放,value进行加一操作。</p> +<h4 id="3信号量使用及管理">3、信号量使用及管理 +</h4><blockquote> +<p>对一个信号量的操作包含:<code>创建/初始化信号量、获取信号量、释放信号量、删除/脱离信号量</code>。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d8bde585ecaa4669817d29f0ffdc34f5.png" +loading="lazy" +></p> +<p>1)动态创建信号量</p> +<blockquote> +<p>当调用这个函数时,系统将先从对象管理器中分配一个 semaphore 对象,并初始化这个对象,然后初始化父类 IPC 对象以及与 semaphore 相关的部分。在创建信号量指定的参数中,信号量标志参数决定了当信号量不可用时,多个线程等待的排队方式。</p> +</blockquote> +<blockquote> +<p>当选择 <code>RT_IPC_FLAG_FIFO(先进先出)</code>方式时,那么等待线程队列将按照先进先出的方式排队,先进入的线程将先获得等待的信号量; +当选择 <code>RT_IPC_FLAG_PRIO(优先级等待)</code>方式时,等待线程队列将按照优先级进行排队,优先级高的等待线程将先获得等待的信号量。</p> +</blockquote> +<p><code>函数声明</code>:</p> +<p><code>rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);</code></p> +<p><code>参数介绍</code>:</p> +<p><img src="https://img-blog.csdnimg.cn/f829de152967470393d8b7605e4c2b12.png" +loading="lazy" +></p> +<p><code>注意:</code></p> +<p><code>(1)此处的*name定义最多只能显示八个字符</code></p> +<p><code>(2)查看rt_sem_create()函数返回值是--&gt;typedef struct rt_semaphore *rt_sem_t;,也就是一个重命名的结构体rt_semaphore </code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// flag值 如下 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_FIFO 0x00 </span><span class="cm">/**&lt; FIFOed IPC. @ref IPC.按照先进先出的方式获取信号量资源 */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_IPC_FLAG_PRIO 0x01 </span><span class="cm">/**&lt; PRIOed IPC. @ref IPC.按线程优先级获取信号量资源 */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>2)动态创建的信号量删除</p> +<blockquote> +<p>系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。</p> +</blockquote> +<blockquote> +<p>调用这个函数时,系统将删除这个信号量。<code>如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。</code></p> +</blockquote> +<p><code>函数声明</code> +<code>rt_err_t rt_sem_delete(rt_sem_t sem);</code></p> +<p><code>实例</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)静态创建信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>对于静态信号量对象,它的内存空间在编译时期就被编译器分配出来,放在读写数据段或未初始化数据段上,此时使用信号量就不再需要使用 rt_sem_create 接口来创建它,而只需在使用前对它进行初始化即可。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">value</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<p><img src="https://img-blog.csdnimg.cn/cbe2c704ffc849cf8859a6c46237681a.png" +loading="lazy" +></p> +<p>4)脱离信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于<code>静态初始化的信号量</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_detach</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>5)获取信号量</p> +<p><code>描述</code></p> +<blockquote> +<p>线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。</p> +<p>如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择<code>直接返回、或挂起等待一段时间、或永久等待</code>,直到其他线程或中断释放该信号量。</p> +<p>如果在参数 time 指定的时间内依然得不到信号量,线程将<code>超时返回</code>,返回值是<code> - RT_ETIMEOUT</code>。</p> +</blockquote> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_take</span> <span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">,</span> <span class="kt">rt_int32_t</span> <span class="n">time</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>参数描述</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// time参数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_FOREVER -1 </span><span class="cm">/**&lt; Block forever until get resource. */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_WAITING_NO 0 </span><span class="cm">/**&lt; Non-block. */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 扩展: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_trytake</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> <span class="c1">// 无等待获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 这个函数与 rt_sem_take(sem, RT_WAITING_NO) 的作用相同,即当线程申请的信号量资源实例不可用的时候,它不会等待在该信号量上,而是直接返回 - RT_ETIMEOUT。 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>6)信号量释放</p> +<p><code>函数声明</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="kt">rt_sem_t</span> <span class="n">sem</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>描述</code></p> +<blockquote> +<p>例如当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加 1。</p> +</blockquote> +<h4 id="4信号量实例演示">4、信号量实例演示 +</h4><blockquote> +<p>这里可以看到创建了两个线程,而且线程的优先级都是符合我们定义的20,但是查看线程状态可以发现,线程1和线程2都是阻塞态。这是因为我们在线程的入口函数中使用了mdelay延时函数,执行这个函数,线程会短暂地进入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/632591398002468c9a69cf3e4ac8cfe4.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>由于我们在线程2的入口函数中执行了信号量获取函数,但是我们在初始化信号量2的时候设定的初值是0,所以此时线程2由于未获取到信号量而陷入阻塞态</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/4293c61a10d14a128312fd50d7d2c9c6.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>查看信号量设定的标志位是<code>RT_IPC_FLAG_FIFO</code>,是按照先进先出的方式进行信号量的获取的,所以在函数的执行顺序中可以发现都是按照线程1-&gt;线程2-&gt;线程1-&gt;线程2&hellip;的顺序执行的,这样就实现了线程的并发互斥运行。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1000730483a345728f1faa2ba68bde2d.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p><img src="https://img-blog.csdnimg.cn/31c3f295be2e41f9ab8d674ade353007.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>最后附上测试源代码</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_sem_t</span> <span class="n">sem1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_semaphore</span> <span class="n">sem2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1</span><span class="p">,</span><span class="n">th2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th1_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">8000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="n">sem1</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">100</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th1_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_take</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="n">RT_WAITING_FOREVER</span><span class="p">);</span><span class="c1">// 获取信号量 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry [%d]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">flags</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_sem_release</span><span class="p">(</span><span class="n">sem1</span><span class="p">);</span><span class="c1">// 对获取的信号量进行释放 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sem1</span> <span class="o">=</span> <span class="nf">rt_sem_create</span><span class="p">(</span><span class="s">&#34;sem_1&#34;</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">sem1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem1 rt_sem_create is success...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">sem2</span><span class="p">,</span> <span class="s">&#34;sem2&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">RT_IPC_FLAG_FIFO</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_create is failure...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;sem2 rt_sem_init successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th1</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th1&#34;</span><span class="p">,</span> <span class="n">th1_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th1</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th1 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">th2</span> <span class="o">=</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="s">&#34;th2&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">th2</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;th2 rt_thread_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_startup</span><span class="p">(</span><span class="n">th2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div>线程管理https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/Sat, 16 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 线程管理" /><p>原理实战请查看<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124539095" target="_blank" rel="noopener" +>【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)</a></p> +<h1 id="一序言">一、序言 +</h1><p>在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。 +同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。</p> +<p>下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:</p> +<blockquote> +<p>1.读取数据 +2.显示数据</p> +</blockquote> +<p>简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。 +<img src="https://img-blog.csdnimg.cn/6d57696f2ffc4e859bf8c8c1ffc0789e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +在RT-Thread 中,与上述子任务对应的程序实体就是线程,<code>线程是实现任务的载体</code>。 +它是RT-Thread中<code>最基本的调度单位</code>,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的<code>优先级</code>,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。 +<code>上下文:</code>当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。</p> +<h1 id="二线程管理的功能特点">二、线程管理的功能特点 +</h1><p>RT-Thread 线程管理的主要功能是<code>对线程进行管理和调度</code>,系统中总共存在两类线程,分别是<code>系统线程</code>和<code>用户线程</code>。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。</p> +<p>如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。 +<img src="https://img-blog.csdnimg.cn/5584a47897de430597897d3a6bddd710.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<ul> +<li>RT-Thread 的线程调度器是<code>抢占式</code>的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。</li> +<li>当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了CPU 的使用权。 +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。</li> +<li>当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程上下文(<code>详细内容可参考</code><a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124145153" target="_blank" rel="noopener" +>【操作系统】进程上下文和线程上下文</a>)信息恢复。</li> +</ul> +<h1 id="三线程的工作机制">三、线程的工作机制 +</h1><h2 id="1线程控制块">1.线程控制块 +</h2><p>在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/* 线程控制块*/ +</span></span><span class="line"><span class="cl">struct rt_thread +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* rt 对象*/ +</span></span><span class="line"><span class="cl"> char name[RT_NAME_MAX]; /* 线程名称*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t type; /* 对象类型*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t flags; /* 标志位*/ +</span></span><span class="line"><span class="cl"> rt_list_t list; /* 对象列表*/ +</span></span><span class="line"><span class="cl"> rt_list_t tlist; /* 线程列表*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 栈指针与入口指针*/ +</span></span><span class="line"><span class="cl"> void *sp; /* 栈指针*/ +</span></span><span class="line"><span class="cl"> void *entry; /* 入口函数指针*/ +</span></span><span class="line"><span class="cl"> void *parameter; /* 参数*/ +</span></span><span class="line"><span class="cl"> void *stack_addr; /* 栈地址指针*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t stack_size; /* 栈大小*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 错误代码*/ +</span></span><span class="line"><span class="cl"> rt_err_t error; /* 线程错误代码*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t stat; /* 线程状态*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t current_priority; /* 当前优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint8_t init_priority; /* 初始优先级*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t number_mask; +</span></span><span class="line"><span class="cl"> ...... +</span></span><span class="line"><span class="cl"> rt_ubase_t init_tick; /* 线程初始化计数值*/ +</span></span><span class="line"><span class="cl"> rt_ubase_t remaining_tick; /* 线程剩余计数值*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> struct rt_timer thread_timer; /* 内置线程定时器*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数*/ +</span></span><span class="line"><span class="cl"> rt_uint32_t user_data; /* 用户数据*/ +</span></span><span class="line"><span class="cl">}; +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li><code> 其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。</code></li> +<li><code>cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。</code></li> +<li><code>最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。</code></li> +</ul> +<h2 id="2线程的重要属性">2.线程的重要属性 +</h2><h4 id="1-线程栈">(1) 线程栈 +</h4><ul> +<li>RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。</li> +<li>线程栈还用来存放函数中的局部变量:函数中的局部变量从线程栈空间中申请;函数中局部变量初始时从寄存器中分配(ARM 架构),当这个函数再调用另一个函数时,这些局部变量将放入栈中。</li> +<li>对于线程第一次运行,可以以手工的方式构造这个上下文来设置一些初始的环境:入口函数(PC 寄存器)、入口参数(R0 寄存器)、返回位置(LR 寄存器)、当前机器运行状态(CPSR 寄存器)。</li> +<li>线程栈的增长方向是芯片构架密切相关的,RT-Thread 3.1.0 以前的版本,均只支持栈由高地址向低地址增长的方式,对于ARM Cortex-M 架构,线程栈可构造如下图所示。 +<img src="https://img-blog.csdnimg.cn/041732b5e1fd43d5a62382931ad50360.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></li> +</ul> +<h4 id="2-线程状态">(2) 线程状态 +</h4><p>线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。 +在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:</p> +<table> +<thead> +<tr> +<th>状态</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>初始态</td> +<td>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</td> +</tr> +<tr> +<td>就绪态</td> +<td>在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY</td> +</tr> +<tr> +<td>运行态</td> +<td>线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING</td> +</tr> +<tr> +<td>挂起态</td> +<td>也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND</td> +</tr> +<tr> +<td>关闭态</td> +<td>当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE</td> +</tr> +</tbody> +</table> +<h4 id="3-线程优先级">(3) 线程优先级 +</h4><ul> +<li> +<p>RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。</p> +</li> +<li> +<p>RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。</p> +</li> +</ul> +<h4 id="4-时间片">(4) 时间片 +</h4><blockquote> +<p>每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。</p> +</blockquote> +<p>假设有2 个<code>优先级相同的就绪态线程A 与B</code>,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。 +<img src="https://img-blog.csdnimg.cn/31c4fb41bf8947c1a47864b12b9e602e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5-线程的入口函数">(5) 线程的入口函数 +</h4><p>线程控制块中的<code>entry</code>是线程的入口函数,它是线程实现预期功能的函数。</p> +<p>线程的入口函数由用户设计实现,一般有以下两种代码形式: +1.<code>无限循环模式</code></p> +<blockquote> +<p>在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外 +界事件的发生,而后进行相应的服务:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void thread_entry(void* paramenter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">while (1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> /* 等待事件的发生*/ +</span></span><span class="line"><span class="cl"> /* 对事件进行服务、进行处理*/ +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。 +所以在实时操作系统中必须注意的一点就是:<!-- raw HTML omitted -->线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。<!-- raw HTML omitted --></p> +</blockquote> +<p>2.<code>顺序执行或有限次循环模式</code></p> +<blockquote> +<p>如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">static void thread_entry(void* parameter) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> /* 处理事务#1 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#2 */ +</span></span><span class="line"><span class="cl"> … +</span></span><span class="line"><span class="cl"> /* 处理事务#3 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6-常见的线程错误码">(6) 常见的线程错误码 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_EOK 0 /* 无错误*/ +</span></span><span class="line"><span class="cl">#define RT_ERROR 1 /* 普通错误*/ +</span></span><span class="line"><span class="cl">#define RT_ETIMEOUT 2 /* 超时错误*/ +</span></span><span class="line"><span class="cl">#define RT_EFULL 3 /* 资源已满*/ +</span></span><span class="line"><span class="cl">#define RT_EEMPTY 4 /* 无资源*/ +</span></span><span class="line"><span class="cl">#define RT_ENOMEM 5 /* 无内存*/ +</span></span><span class="line"><span class="cl">#define RT_ENOSYS 6 /* 系统不支持*/ +</span></span><span class="line"><span class="cl">#define RT_EBUSY 7 /* 系统忙*/ +</span></span><span class="line"><span class="cl">#define RT_EIO 8 /* IO 错误*/ +</span></span><span class="line"><span class="cl">#define RT_EINTR 9 /* 中断系统调用*/ +</span></span><span class="line"><span class="cl">#define RT_EINVAL 10 /* 非法参数*/ +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3线程状态切换">3.线程状态切换 +</h2><p>RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示: +<img src="https://img-blog.csdnimg.cn/3c79cc6198144f02b4830d4521384c30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<ul> +<li>线程通过调用函数<code>rt_thread_create/init()</code> 进入到初始状态<code>(RT_THREAD_INIT)</code>;</li> +<li>初始状态的线程通过调用函数<code>rt_thread_startup()</code> 进入到就绪状态<code>(RT_THREAD_READY)</code>;</li> +<li>就绪状态的线程被调度器调度后进入运行状态<code>(RT_THREAD_RUNNING)</code>;</li> +<li>当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态<code>(RT_THREAD_SUSPEND)</code>;</li> +</ul> +</blockquote> +<blockquote> +<ul> +<li>处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。</li> +<li>挂起状态的线程,如果调用<code>rt_thread_delete/detach() </code>函数,将更改为关闭状态<code>(RT_THREAD_CLOSE)</code>;</li> +<li>而运行状态的线程,如果运行结束,就会在线程的最后部分执行<code>rt_thread_exit() </code>函数,将状态更改为关闭状态。</li> +</ul> +</blockquote> +<p><!-- raw HTML omitted --><code>!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。</code></p> +<h2 id="4系统线程">4.系统线程 +</h2><p>系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。</p> +<h4 id="1空闲线程">(1)空闲线程 +</h4><p><code>空闲线程</code>是系统创建的最低优先级的线程,线程状态<code>永远为就绪态</code>。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。</p> +<p>另外,空闲线程在RT-Thread 也有着它的特殊用途:</p> +<ul> +<li>若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。</li> +<li>空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。(关于<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>钩子函数</a>和<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5ev7%5earticle_score_rank,157%5ev4%5econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>看门狗</a>不懂的可以看这里)</li> +</ul> +<h4 id="2-主线程">(2) 主线程 +</h4><p>在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。</p> +<p>过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 +<img src="https://img-blog.csdnimg.cn/b08911ca57334476945d473ab814f006.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h1 id="四线程的管理方式">四、线程的管理方式 +</h1><p>可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。</p> +<p>动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。</p> +<p>下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。 +<img src="https://img-blog.csdnimg.cn/fea91f8134b648ccaefeb5cf201de15f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="1创建和删除线程">1.创建和删除线程 +</h2><h4 id="1创建线程">(1)创建线程 +</h4><p>一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_thread_t</span> <span class="n">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。</p> +</blockquote> +<p>线程创建rt_thread_create() 的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/f1ba4c76de384fcc91060025bff4bef7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2删除线程">(2)删除线程 +</h4><p>对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:</p> +<pre><code>rt_err_t rt_thread_delete(rt_thread_t thread); +</code></pre> +<p>调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。</p> +<p>线程删除rt_thread_delete() 接口的参数和返回值见下图: +<img src="https://img-blog.csdnimg.cn/eb9a07efdd95454c8873506f5178d1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。</code></p> +<h2 id="2初始化和脱离线程">2.初始化和脱离线程 +</h2><h4 id="1初始化线程">(1)初始化线程 +</h4><p><code>线程的初始化</code>可以使用下面的函数接口完成,来初始化静态线程对象:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">rt_err_t</span> <span class="n">rt_thread_init</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="n">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="n">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="n">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/c1e6ca6ef6b84ebe93d0888ff71332af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2脱离线程">(2)脱离线程 +</h4><p>对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:</p> +<pre><code>rt_err_t rt_thread_detach (rt_thread_t thread); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>thread</td> +<td>线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT_EOK</td> +<td>线程脱离成功</td> +</tr> +<tr> +<td>-RT_ERROR</td> +<td>线程脱离失败</td> +</tr> +</tbody> +</table> +<h2 id="3启动线程">3.启动线程 +</h2><p>创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:</p> +<pre><code>rt_err_t rt_thread_startup(rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/431f38ae0feb46dc833f9835ec57577e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<blockquote> +<p>当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启 +动的线程优先级比当前线程优先级高,将立刻切换到这个线程。</p> +</blockquote> +<h2 id="4获得当前线程">4.获得当前线程 +</h2><p>在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:</p> +<pre><code>rt_thread_t rt_thread_self(void); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/33c1e79ddc8b42c0a28237a91e67b92c.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="5使线程出让处理器资源">5.使线程出让处理器资源 +</h2><blockquote> +<p>当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。</p> +</blockquote> +<p>线程让出处理器使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_yield(void); +</code></pre> +<blockquote> +<p>调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。</p> +</blockquote> +<h2 id="6使线程睡眠">6.使线程睡眠 +</h2><blockquote> +<p>在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。</p> +</blockquote> +<p>线程睡眠可使用以下三个函数接口:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_thread_sleep(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_delay(rt_tick_t tick); +</span></span><span class="line"><span class="cl">rt_err_t rt_thread_mdelay(rt_int32_t ms); +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/6ebefaeea61f48a7b26d43e0d6589055.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="7挂起和恢复线程">7.挂起和恢复线程 +</h2><h4 id="1线程挂起">(1)线程挂起 +</h4><blockquote> +<ul> +<li>当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。</li> +<li>处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。</li> +</ul> +</blockquote> +<p><code>线程挂起</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_suspend (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/eed2dcfd794040798637c029b253fb87.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +> +<code>!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。</code></p> +<h4 id="2恢复线程">(2)恢复线程 +</h4><blockquote> +<p>恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在 +所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。</p> +</blockquote> +<p><code>线程恢复</code>使用下面的函数接口:</p> +<pre><code>rt_err_t rt_thread_resume (rt_thread_t thread); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/0640fc789a1645d3b424f605d3aca937.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="8控制线程">8.控制线程 +</h2><p>当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:</p> +<pre><code>rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); +</code></pre> +<p><img src="https://img-blog.csdnimg.cn/348eb561864549528d9695d8f504af92.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<pre><code>指示控制命令cmd 当前支持的命令包括: +•RT_THREAD_CTRL_CHANGE_PRIORITY:动态更改线程的优先级; +•RT_THREAD_CTRL_STARTUP:开始运行一个线程,等同于rt_thread_startup() 函数调用; +•RT_THREAD_CTRL_CLOSE:关闭一个线程,等同于rt_thread_delete() 函数调用。 +</code></pre> +<h2 id="设置和删除空闲钩子">设置和删除空闲钩子 +</h2><blockquote> +<p>空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。</p> +</blockquote> +<p>设置/ 删除空闲钩子的接口如下:</p> +<pre><code>rt_err_t rt_thread_idle_sethook(void (*hook)(void)); +rt_err_t rt_thread_idle_delhook(void (*hook)(void)); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>设置/删除的钩子函数</td> +</tr> +<tr> +<td>返回</td> +<td>&mdash;</td> +</tr> +<tr> +<td>RT-EOK</td> +<td>设置/删除成功</td> +</tr> +<tr> +<td>-RT_EFULL</td> +<td>设置失败</td> +</tr> +<tr> +<td>-RT_ENOSYS</td> +<td>删除失败</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。</code></p> +<h2 id="10设置调度器钩子">10.设置调度器钩子 +</h2><p><code>在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。</code></p> +<p>在系统线程切换时,这个钩子函数将被调用:</p> +<pre><code>void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); +</code></pre> +<p><code>设置调度器钩子函数的输入参数</code>如下表所示:</p> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>hook</td> +<td>表示用户定义的钩子函数指针</td> +</tr> +</tbody> +</table> +<p><code>钩子函数hook() 的声明</code>如下:</p> +<pre><code>void hook(struct rt_thread* from, struct rt_thread* to); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>from</td> +<td>表示系统所要切换出的线程控制块指针</td> +</tr> +<tr> +<td>to</td> +<td>表示系统所要切换到的线程控制块指针</td> +</tr> +</tbody> +</table> +<p><code>!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。</code></p> +<hr> +<p>资料参考: +(1)<a class="link" href="https://blog.csdn.net/as480133937/article/details/99121645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164983700616780269879215%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164983700616780269879215&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-99121645.142%5Ev7%5Earticle_score_rank,157%5Ev4%5Econtrol&amp;utm_term=%E7%9C%8B%E9%97%A8%E7%8B%97&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>【STM32】HAL库 STM32CubeMX教程五&mdash;-看门狗(独立看门狗,窗口看门狗)</a> +(2)<a class="link" href="https://blog.csdn.net/u010132177/article/details/110704721?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-110704721.nonecase&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>什么是钩子函数</a> +(3)<a class="link" href="https://www.rt-thread.org/document/site/#/" target="_blank" rel="noopener" +>RT-Thread文档中心</a></p>I2C(内核学习)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadi2c%E5%86%85%E6%A0%B8%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post I2C(内核学习)" /><h2 id="一i2c协议">一、i2c协议 +</h2><p>由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。</p> +<h2 id="二i2c物理层">二、i2c物理层 +</h2><ul> +<li> +<p>i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。 +<code>SDA</code>:用于传输数据 +<code>SCL</code>:用于同步数据收发</p> +</li> +<li> +<p>每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问</p> +</li> +<li> +<p>i2c支持多主控,任何时间点都只能有一个主控。 +<img src="https://img-blog.csdnimg.cn/01cc1805f0db4842a836a7dae9b11978.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +</li> +<li> +<p>i2c器件的SDA引脚和SCL引脚是开漏电路<a class="link" href="https://blog.csdn.net/ngulb/article/details/81174233?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=%E5%BC%80%E6%BC%8F%E7%94%B5%E8%B7%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81174233.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>形式,因此,SDA和SCL总线都需要连接上拉电阻<a class="link" href="https://blog.csdn.net/fymx203/article/details/89426403?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164973690016782092947037%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164973690016782092947037&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-89426403.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E4%B8%8A%E6%8B%89%E7%94%B5%E9%98%BB&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>(参照资料)</a>,当总线空闲时,两条总线均为高电平。</p> +</li> +<li> +<p>各器件的SDA和SCL信号线在总线上都是<code>线与</code>关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)</p> +</li> +</ul> +<h2 id="三i2c协议层">三、i2c协议层 +</h2><p>协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。</p> +<h4 id="1i2c总线的位传输">1.i2c总线的位传输 +</h4><p>数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。 +数据改变:当SCL为低电平时,SDA才可以改变电平 +<code>i2c位传输时序图</code> +<img src="https://img-blog.csdnimg.cn/3bcc9522f82841b5a9808703e4c29fa9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2i2c总线的开始和结束信号">2.i2c总线的开始和结束信号 +</h4><p><code>开始信号</code>:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 +<code>结束信号</code>:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。</p> +<h4 id="3i2c应答信号">3.i2c应答信号 +</h4><ul> +<li>在<code>主机</code>发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答<code>ACK</code>(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)</li> +<li>当<code>从机</code>接收不到数据或通信故障时,<code>从机</code>必须使SDA保持高电平,<code>主机</code>产生一个结束信号终止传输或者产生新的传输。</li> +</ul> +<h4 id="4i2c总线的仲裁机制">4.i2c总线的仲裁机制 +</h4><ul> +<li>SDA的仲裁也是建立在总线具有<code>线与</code>逻辑功能的原理上的。</li> +<li>节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。</li> +<li>SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)</li> +<li>当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是<code>线与</code>连接。</li> +</ul> +<h2 id="四访问i2c总线设备">四、访问i2c总线设备 +</h2><p>一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:</p> +<table> +<thead> +<tr> +<th>函数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>rt_device_find()</td> +<td>根据I2C 总线设备名称查找设备获取设备<a class="link" href="https://blog.csdn.net/wyx0224/article/details/83385168?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164976053816780265492902%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=164976053816780265492902&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-83385168.142%5ev7%5epc_search_result_control_group,157%5ev4%5econtrol&amp;utm_term=%E5%8F%A5%E6%9F%84&amp;spm=1018.2226.3001.4187" target="_blank" rel="noopener" +>句柄</a></td> +</tr> +<tr> +<td>rt_i2c_transfer()</td> +<td>传输数据</td> +</tr> +</tbody> +</table> +<h2 id="五查找i2c总线设备">五、查找i2c总线设备 +</h2><p>在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,</p> +<pre><code>rt_device_t rt_device_find(const char* name); +</code></pre> +<table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td>i2c总线设备名称</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>&ndash;</td> +</tr> +<tr> +<td>设备句柄</td> +<td>查找到对应设备将返回相应的设备句柄</td> +</tr> +<tr> +<td>RT-NULL</td> +<td>没有找到相应的设备对象</td> +</tr> +</tbody> +</table> +<p>一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六数据传输">六、数据传输 +</h2><p>获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs[], +</span></span><span class="line"><span class="cl"> rt_uint32_t num); +</span></span></code></pre></td></tr></table> +</div> +</div><table> +<thead> +<tr> +<th>参数</th> +<th>描述</th> +</tr> +</thead> +<tbody> +<tr> +<td>bus</td> +<td>i2c总线设备句柄</td> +</tr> +<tr> +<td>msgs[]</td> +<td>待传输的消息数组指针</td> +</tr> +<tr> +<td>num</td> +<td>消息数组的元素个数</td> +</tr> +<tr> +<td><!-- raw HTML omitted -->返回</td> +<td>-</td> +</tr> +<tr> +<td>-</td> +<td>-</td> +</tr> +<tr> +<td>消息数组的元素个数</td> +<td>成功</td> +</tr> +<tr> +<td>错误码</td> +<td>失败</td> +</tr> +</tbody> +</table> +<ul> +<li>和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。</li> +<li>参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。 +<code>!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。</code></li> +</ul> +<blockquote> +<p>I2C 消息数据结构原型如下:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">struct rt_i2c_msg +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl">rt_uint16_t addr; /* 从机地址*/ +</span></span><span class="line"><span class="cl">rt_uint16_t flags; /* 读、写标志等*/ +</span></span><span class="line"><span class="cl">rt_uint16_t len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl">rt_uint8_t *buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。</li> +<li>标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。 +<code>!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。</code></li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define RT_I2C_WR 0x0000 /* 写标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_RD (1u &lt;&lt; 0) /* 读标志*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_ADDR_10BIT (1u &lt;&lt; 2) /* 10 位地址模式*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_START (1u &lt;&lt; 4) /* 无开始条件*/ +</span></span><span class="line"><span class="cl">#define RT_I2C_IGNORE_NACK (1u &lt;&lt; 5) /* 忽视NACK */ +</span></span><span class="line"><span class="cl">#define RT_I2C_NO_READ_ACK (1u &lt;&lt; 6) /* 读的时候不发送ACK */ +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>使用示例如下所示:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/ +</span></span><span class="line"><span class="cl">#define AHT10_ADDR 0x38 /* 从机地址*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">struct rt_i2c_bus_device *i2c_bus; /* I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 查找I2C总线设备, 获取I2C总线设备句柄*/ +</span></span><span class="line"><span class="cl">i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">/* 读传感器寄存器数据*/ +</span></span><span class="line"><span class="cl">static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t +</span></span><span class="line"><span class="cl">*buf) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> struct rt_i2c_msg msgs; +</span></span><span class="line"><span class="cl"> msgs.addr = AHT10_ADDR; /* 从机地址*/ +</span></span><span class="line"><span class="cl"> msgs.flags = RT_I2C_RD; /* 读标志*/ +</span></span><span class="line"><span class="cl"> msgs.buf = buf; /* 读写数据缓冲区指针 */ +</span></span><span class="line"><span class="cl"> msgs.len = len; /* 读写数据字节数*/ +</span></span><span class="line"><span class="cl"> /* 调用I2C设备接口传输数据*/ +</span></span><span class="line"><span class="cl"> if (rt_i2c_transfer(bus, &amp;msgs, 1) == 1) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return RT_EOK; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> return -RT_ERROR; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="七i2c-总线设备使用示例">七、I2C 总线设备使用示例 +</h2><p>I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:</p> +<ol> +<li>首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。</li> +<li>控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() +这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。</li> +</ol> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">/*</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序清单:</span> <span class="err">这是一个</span><span class="n">I2C</span> <span class="err">设备使用例程</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">例程导出了</span><span class="n">i2c_aht10_sample</span> <span class="err">命令到控制终端</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令调用格式:</span> <span class="n">i2c_aht10_sample</span> <span class="n">i2c1</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">命令解释:</span> <span class="err">命令第二个参数是要使用的</span><span class="n">I2C总线设备名称</span><span class="err">,</span> <span class="err">为空则使用默认的</span><span class="n">I2C总线设备</span> +</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="err">程序功能:</span> <span class="err">通过</span><span class="n">I2C</span> <span class="err">设备读取温湿度传感器</span><span class="n">aht10</span> <span class="err">的温湿度数据并打印</span> +</span></span><span class="line"><span class="cl"><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtthread.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;rtdevice.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_I2C_BUS_NAME &#34;i2c1&#34; /* 传感器连接的I2C总线设备名称*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_ADDR 0x38 /* 从机地址*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_NORMAL_CMD 0xA8 /* 一般命令*/</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define AHT10_GET_DATA 0xAC /* 获取数据命令*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">i2c_bus</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> <span class="o">/*</span> <span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_bool_t</span> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_FALSE</span><span class="p">;</span> <span class="o">/*</span> <span class="err">传感器初始化状态</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">写传感器寄存器</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">write_reg</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">reg</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">reg</span><span class="p">;</span> <span class="o">//</span><span class="n">cmd</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_WR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">读传感器寄存器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">rt_err_t</span> <span class="n">read_regs</span><span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="n">bus</span><span class="p">,</span> <span class="n">rt_uint8_t</span> <span class="n">len</span><span class="p">,</span> <span class="n">rt_uint8_t</span><span class="o">*</span><span class="n">buf</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">struct</span> <span class="n">rt_i2c_msg</span> <span class="n">msgs</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">addr</span> <span class="o">=</span> <span class="n">AHT10_ADDR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">RT_I2C_RD</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">buf</span> <span class="o">=</span> <span class="n">buf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">msgs</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">调用</span><span class="n">I2C设备接口传输数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">rt_i2c_transfer</span><span class="p">(</span><span class="n">bus</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msgs</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">read_temp_humi</span><span class="p">(</span><span class="ne">float</span> <span class="o">*</span><span class="n">cur_temp</span><span class="p">,</span> <span class="ne">float</span> <span class="o">*</span><span class="n">cur_humi</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_GET_DATA</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">/*</span> <span class="err">发送命令</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_regs</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> <span class="o">/*</span> <span class="err">获取传感器数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">湿度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_humi</span> <span class="o">=</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">12</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span> <span class="o">|</span> <span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf0</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">*</span> <span class="mf">100.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span><span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">温度数据转换</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">cur_temp</span> <span class="o">=</span> <span class="p">((</span><span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mh">0xf</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span> <span class="o">|</span> <span class="n">temp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="o">*</span> <span class="mf">200.0</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">)</span><span class="o">-</span> <span class="mi">50</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">aht10_init</span><span class="p">(</span><span class="k">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_uint8_t</span> <span class="n">temp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">查找</span><span class="n">I2C总线设备</span><span class="err">,</span> <span class="err">获取</span><span class="n">I2C总线设备句柄</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">i2c_bus</span> <span class="o">=</span> <span class="p">(</span><span class="n">struct</span> <span class="n">rt_i2c_bus_device</span> <span class="o">*</span><span class="p">)</span><span class="n">rt_device_find</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i2c_bus</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;can&#39;t find </span><span class="si">%s</span><span class="s2"> device!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_NORMAL_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x08</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">write_reg</span><span class="p">(</span><span class="n">i2c_bus</span><span class="p">,</span> <span class="n">AHT10_CALIBRATION_CMD</span><span class="p">,</span> <span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_thread_mdelay</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">initialized</span> <span class="o">=</span> <span class="n">RT_TRUE</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">void</span> <span class="n">i2c_aht10_sample</span><span class="p">(</span><span class="ne">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="ne">float</span> <span class="n">humidity</span><span class="p">,</span> <span class="n">temperature</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">char</span> <span class="n">name</span><span class="p">[</span><span class="n">RT_NAME_MAX</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">humidity</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">temperature</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_strncpy</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">AHT10_I2C_BUS_NAME</span><span class="p">,</span> <span class="n">RT_NAME_MAX</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">传感器初始化</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">aht10_init</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">initialized</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">/*</span> <span class="err">读取温湿度数据</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">read_temp_humi</span><span class="p">(</span><span class="o">&amp;</span><span class="n">temperature</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">humidity</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor humidity : </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2"> </span><span class="si">%%</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">humidity</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">humidity</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span> <span class="n">temperature</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;read aht10 sensor temperature: </span><span class="si">%d</span><span class="s2">.</span><span class="si">%d</span><span class="s2">°C</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">)</span><span class="n">temperature</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="ne">int</span><span class="p">)(</span><span class="o">-</span><span class="n">temperature</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">rt_kprintf</span><span class="p">(</span><span class="s2">&#34;initialize sensor failed!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="o">/*</span> <span class="err">导出到</span><span class="n">msh</span> <span class="err">命令列表中</span><span class="o">*/</span> +</span></span><span class="line"><span class="cl"><span class="n">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">i2c_aht10_sample</span><span class="p">,</span> <span class="n">i2c</span> <span class="n">aht10</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>学习资料参考:<a class="link" href="https://item.jd.com/10022312146340.html" target="_blank" rel="noopener" +>《嵌入式系统设计》</a>、<a class="link" href="https://club.rt-thread.org/index.html" target="_blank" rel="noopener" +>RT-Thread</a></p>RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/Fri, 15 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A81%E6%8C%89%E9%94%AE%E6%8E%A7%E5%88%B6%E7%94%B5%E6%9C%BA%E6%AD%A3%E5%8F%8D%E8%BD%AC%E8%9C%82%E9%B8%A3%E5%99%A8/cover.jpg" alt="Featured image of post RT-Thread Studio使用(1)(按键控制电机正反转、蜂鸣器)" /><h2 id="一初识rt-thread">一、初识RT-Thread +</h2><p><code>做世界级的 OS,让万物互联,信息畅通无阻。</code> +<code>成为未来 AIoT 领域最为主流的操作系统平台。</code></p> +<h4 id="1简介">1.简介 +</h4><blockquote> +<p>RT-Thread 是一个集<code>实时操作系统(RTOS)内核、中间件组件和开发者社区于一体</code>的技术平台,由<code>熊谱翔先生</code>带领并集合开源社区力量开发而成,RT-Thread 也是一个<code>组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性</code>的<code>物联网操作系统</code>。</p> +</blockquote> +<h4 id="2前景">2.前景 +</h4><blockquote> +<p>RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个<code>国内最大的嵌入式开源社区</code>,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人<code>自主开发</code>、国内最成熟稳定和装机量最大的<code>开源 RTOS</code>。</p> +</blockquote> +<h4 id="3软件生态">3.软件生态 +</h4><blockquote> +<p>RT-Thread 拥有<code>良好的软件生态</code>,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。</p> +</blockquote> +<h2 id="二实验准备">二、实验准备 +</h2><ul> +<li>编程工具:<code>RT-Thread studio</code></li> +<li>开发板:<code>潘多拉STM32L475</code></li> +</ul> +<hr> +<h2 id="三实验需求">三、实验需求 +</h2><ul> +<li>1.使用按键控制蜂鸣器和电机,当按下KEY0 后电机左转,当按下KEY1 后电机 +右转,当按下KEY2 后电机停止,当按住WK_UP 时蜂鸣器鸣叫,松开WK_UP 后蜂鸣器关闭。</li> +<li>2.其中KEY0 KEY1 KEY2 三个按键会触发中断,通过pin 设备的中断回调函数控制电机,WK_UP 按键通过轮询的方式控制蜂鸣器鸣叫。</li> +</ul> +<h2 id="四操作流程">四、操作流程 +</h2><h4 id="1新建rt-thread工程">1.新建RT-Thread工程 +</h4><p><img src="https://img-blog.csdnimg.cn/85370c1057554323ba75dd83c3d1844f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="2rt-thread-studio界面介绍">2.RT-Thread Studio界面介绍 +</h4><p><img src="https://img-blog.csdnimg.cn/b24064da660f40b5b00e9e0f03d4f1ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="3代码编写">3.代码编写 +</h4><p><img src="https://img-blog.csdnimg.cn/c556436b0d44443686dafa3a0f389bd5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="4烧录">4.烧录 +</h4><p><img src="https://img-blog.csdnimg.cn/c5ea1524e61e4b92af667e17decd12bb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h4 id="5串口监视">5.串口监视 +</h4><p><img src="https://img-blog.csdnimg.cn/eae3d5a76ae14aa0a7e6a2d00145024d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<h2 id="五代码演示">五、代码演示 +</h2><p><code>1.头文件</code></p> +<pre><code>#include &lt;rtthread.h&gt; +#include &lt;rtdevice.h&gt; +#include &lt;board.h&gt; +</code></pre> +<p><code>2.宏定义</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">//</span><span class="err">按键初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY0 GET_PIN(D, 10) // PD10: KEY0 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY1 GET_PIN(D, 9) // PD9: KEY1 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_KEY2 GET_PIN(D, 8) // PD8: KEY2 --&gt; KEY</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_WK_UP GET_PIN(C,13)//PC13:WK_UP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">电机初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_A GET_PIN(A,1)//PA1:MOTOR_A</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_MOTOR_B GET_PIN(A,0)//PA0:MOTOR_B</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="err">蜂鸣器初始化</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define PIN_BEEP GET_PIN(B,2)//PB2:BEEP</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">enum</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_STOP</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_LEFT</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">MOTOR_RIGHT</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>3.void motor_ctrl(rt_uint8_t turn) //电机控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void motor_ctrl(rt_uint8_t turn) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (turn == MOTOR_STOP) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_LEFT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_LOW); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else if (turn == MOTOR_RIGHT) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_A, PIN_HIGH); +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_MOTOR_B, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;err parameter ! Please enter 0-2.&#34;); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void beep_ctrl(rt_uint8_t on) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> if (on) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_HIGH); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_pin_write(PIN_BEEP, PIN_LOW); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.void irq_callback(void *args) // 中断回调函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">void irq_callback(void *args) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> rt_uint32_t sign = (rt_uint32_t)args; +</span></span><span class="line"><span class="cl"> switch (sign) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> case PIN_KEY0: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_LEFT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY0 interrupt. motor turn left.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY1: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_RIGHT); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY1 interrupt. motor turn right.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> case PIN_KEY2: +</span></span><span class="line"><span class="cl"> motor_ctrl(MOTOR_STOP); +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;KEY2 interrupt. motor stop.&#34;); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> default: +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;error sign= %d !&#34;, sign); +</span></span><span class="line"><span class="cl"> break; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>5.主函数</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int main(void) +</span></span><span class="line"><span class="cl">{ +</span></span><span class="line"><span class="cl"> unsigned int count = 1; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置电机控制引脚为输入模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_A, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_MOTOR_B, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置蜂鸣器引脚为输出模式*/ +</span></span><span class="line"><span class="cl"> rt_pin_mode(PIN_BEEP, PIN_MODE_OUTPUT); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 设置按键中断模式与中断回调函数*/ +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY0 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY1 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING , irq_callback , (void *)PIN_KEY2 +</span></span><span class="line"><span class="cl"> ); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> /* 使能中断*/ +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE); +</span></span><span class="line"><span class="cl"> while (count &gt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(50); +</span></span><span class="line"><span class="cl"> if (rt_pin_read(PIN_WK_UP) == PIN_HIGH) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> rt_kprintf(&#34;WK_UP pressed. beep on.&#34;); +</span></span><span class="line"><span class="cl"> beep_ctrl(1); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> else +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> beep_ctrl(0); +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> rt_thread_mdelay(10); +</span></span><span class="line"><span class="cl"> count++; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> return 0; +</span></span><span class="line"><span class="cl">} +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="六原理讲解">六、原理讲解 +</h2><p><!-- raw HTML omitted -->通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。 +1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作 +2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。<!-- raw HTML omitted --></p> +<table> +<thead> +<tr> +<th>按键</th> +<th>功能</th> +</tr> +</thead> +<tbody> +<tr> +<td>KEY0</td> +<td>电机左转</td> +</tr> +<tr> +<td>KEY1</td> +<td>电机右转</td> +</tr> +<tr> +<td>KEY2</td> +<td>电机停止</td> +</tr> +<tr> +<td>WK_UP</td> +<td>蜂鸣器响</td> +</tr> +</tbody> +</table>RT-Thread Studio使用 2.内核实战篇(线程)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/Thu, 14 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread-studio%E4%BD%BF%E7%94%A8-2.%E5%86%85%E6%A0%B8%E5%AE%9E%E6%88%98%E7%AF%87%E7%BA%BF%E7%A8%8B/cover.jpg" alt="Featured image of post RT-Thread Studio使用 2.内核实战篇(线程)" /><p>详细原理参考:<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<h2 id="一线程创建">一、线程创建 +</h2><h4 id="1函数原型">1、函数原型 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 线程创建 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_thread_t</span> <span class="nf">rt_thread_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>首先我们来看看线程创建函数返回值类型:</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/de83fe0a4aad4ffe9989eacdf86e96df.png" +loading="lazy" +></p> +<blockquote> +<p>可以看到线程创建函数的返回值类型为:<code>rt_thread_t</code>,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/1dfc5d7964484cae9cc44d8067ffcdd0.png" +loading="lazy" +></p> +<h4 id="2线程定义">2、线程定义 +</h4><p>那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_thread_t</span> <span class="n">th1_ptr</span> <span class="o">=</span> <span class="nb">NULL</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>接下来就是我们给进程控制块传参了</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/90d481586b964d01958c9a14a2bd4695.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/7f39dba639bb4c5faeed06524f57a60d.png" +loading="lazy" +></p> +<h4 id="3线程创建判断">3、线程创建判断 +</h4><p>由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功</p> +<p>我们先来看下线程返回值(如下图)</p> +<blockquote> +<p>如果<code>成功创建</code>的话,返回值是会返回我们所创建的线程对象的</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b19a07990b2240728d423f2c7064d47c.png" +loading="lazy" +></p> +<blockquote> +<p>如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/faf3ad30a6f046638db1c77a0c8275a4.png" +loading="lazy" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span><span class="p">(</span><span class="n">th1_ptr</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//错误信息打印 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_thread_create create failed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ENOMEM</span><span class="p">;</span> <span class="c1">// 设定当线程th1_ptr创建失败后,返回一个空间不足的标志 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">//打印debug调试信息 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_thread_create create successed ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4线程入口函数">4、线程入口函数 +</h4><p>我们在线程的入口处理函数写一个循环函数:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源</code></p> +<ul> +<li>编译,串口观察</li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/4c5556830c644e48bfa76008218fb680.png" +loading="lazy" +></p> +<p>由于RTT studio有内置的串口终端,我们直接打开</p> +<p><img src="https://img-blog.csdnimg.cn/cd4fd4b573c0421a88a73d9f8e7160dd.png" +loading="lazy" +></p> +<p>终端输入list_thread可以查看所有的线程</p> +<p><img src="https://img-blog.csdnimg.cn/edae1f6480c54759915145477406f17d.png" +loading="lazy" +></p> +<h4 id="5总结">5、总结 +</h4><p>这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?</p> +<p>其实我们再看th_demo线程的状态可以看到是<code>init</code>,参考<a class="link" href="https://blog.csdn.net/qq_56914146/article/details/124141250" target="_blank" rel="noopener" +>【玩转RT-Thread】线程管理(详细原理)</a></p> +<p><code>当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT</code></p> +<p>其实这句话就表明当<code>线程处于初始化状态下是不参与系统调度</code>的!</p> +<h4 id="6补充">6、补充 +</h4><p>线程错误码:</p> +<p><img src="https://img-blog.csdnimg.cn/f32f5440cb604b2d8eea4a4546d977b0.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<hr> +<h2 id="二线程启动">二、线程启动 +</h2><p>函数原型</p> +<p>在主函数中加入命令,使线程进入就绪态:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_thread_startup(th1_ptr); +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为<code>挂起态</code></p> +<p><img src="https://img-blog.csdnimg.cn/f5f40f386046488f89e56ab8ee8db6d4.png" +loading="lazy" +></p> +<p><code>解释:</code>虽然我们调用<code>rt_thread_startup</code>函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了<code>rt_thread_mdelay</code>函数使其有一定时间的休眠,从而进入了挂起态`</p> +<h2 id="三初始化线程">三、初始化线程 +</h2><p><code>rt_thread_init</code></p> +<h4 id="1函数声明">1、函数声明 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 模板函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">rt_err_t</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="k">struct</span> <span class="n">rt_thread</span><span class="o">*</span> <span class="kr">thread</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">entry</span><span class="p">)(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">),</span> <span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span><span class="o">*</span> <span class="n">stack_start</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">stack_size</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">priority</span><span class="p">,</span> <span class="kt">rt_uint32_t</span> <span class="n">tick</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2函数定义">2、函数定义 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">ret</span> <span class="o">=</span> <span class="nf">rt_thread_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">th2</span><span class="p">,</span><span class="s">&#34;th2_demo&#34;</span><span class="p">,</span> <span class="n">th2_entry</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">th2_stack</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">th2_stack</span><span class="p">),</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>此处我们需要定义一个ret整型变量用于<code>rt_thread_init</code>的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/b7ce209e742948a398d235d4fd799279.png" +loading="lazy" +></p> +<p><img src="https://img-blog.csdnimg.cn/06a57b94d88c4cdf97f9a431d1578862.png" +loading="lazy" +></p> +<h4 id="3线程入口函数">3、线程入口函数 +</h4><p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">th2_entry</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">10</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;th2_entry running ...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_thread_mdelay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4判断创建状态">4、判断创建状态 +</h4><p>静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用<code>rt_thread_startup</code>函数使线程2进入就绪态,并执行线程处理函数。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">if(ret &lt; 0) +</span></span><span class="line"><span class="cl"> { +</span></span><span class="line"><span class="cl"> LOG_E(&#34;rt2_thread_create create failed ...\n&#34;); // 错误信息打印 +</span></span><span class="line"><span class="cl"> return ret; +</span></span><span class="line"><span class="cl"> } +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> LOG_D(&#34;rt_thread2_create create successes ...\n&#34;); +</span></span><span class="line"><span class="cl"> rt_thread_startup(&amp;th2); // 创建成功后,我们开启线程,使其进入就绪态 +</span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启</p> +</blockquote> +<h4 id="5实验结果">5、实验结果 +</h4><blockquote> +<p>分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/861754f210a74896a6d63d20fbb629f0.png" +loading="lazy" +></p> +<blockquote> +<p>线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/85333e4d1b1942d6a59b10e528797ecc.png" +loading="lazy" +></p>时钟管理(原理+实战)https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/Wed, 13 Jul 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E6%97%B6%E9%92%9F%E7%AE%A1%E7%90%86%E5%8E%9F%E7%90%86-%E5%AE%9E%E6%88%98/cover.jpg" alt="Featured image of post 时钟管理(原理+实战)" /><h2 id="一时钟节拍">一、时钟节拍 +</h2><p>任何操作系统都需要提供一个时钟节拍, 以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。</p> +<p>RT-Thread 中,时钟节拍的长度可以根据 <code>RT_TICK_PER_SECOND</code> 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。也就是说,在RT-Thread中,<code>系统的时钟节拍频率是由RT_TICK_PER_SECOND决定的!</code></p> +<p>rtconfig.h配置文件中定义:</p> +<blockquote> +<ul> +<li> +<p>频率是1000HZ周期是1/1000 s</p> +</li> +<li> +<p>所以节拍是1ms</p> +</li> +<li> +<p>#define RT_ <em>TiCK</em> PER_ SECOND 1000</p> +</li> +</ul> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/d00c117cba6245909ad5fdab19c9bf74.png" +loading="lazy" +></p> +<h4 id="1void-systick_handler">1、void SysTick_Handler() +</h4><p>在RT-Thread中,当系统滴答定时器时间到了的时候,就会执行<code>void SysTick_Handler</code>(系统滴答定时器中断处理函数)这个回调函数(中断处理函数)</p> +<p><img src="https://img-blog.csdnimg.cn/c97f508be8c844a7bfa08cff57233dc1.png" +loading="lazy" +></p> +<blockquote> +<p>可以发现在<code>void SysTick_Handler()</code>这个函数中,首先会执行中断入口函数,然后<code>void rt_tick_increase</code>对<code>rt_tick</code>(系统滴答时钟,初值为0,静态<code>全局变量</code>)进行自加操作,会记录从启动到现在的时钟节拍数</p> +</blockquote> +<h4 id="2void-rt_tick_increase">2、void rt_tick_increase() +</h4><p><img src="https://img-blog.csdnimg.cn/b7122a14e60444e29f36e106bfb5166d.png" +loading="lazy" +></p> +<p><code>也就是说,系统滴答定时器中断处理函数会每1ms触发一次systick定时器中断 </code></p> +<h4 id="3rt_tick_getvoid">3、rt_tick_get(void); +</h4><p>名称:获取系统统计函数</p> +<p>功能:返回当前操作系统的时钟数</p> +<p>返回值:返回当前时钟数</p> +<p><img src="https://img-blog.csdnimg.cn/dd9e18ad7b4942ce9af13f1870fcc232.png" +loading="lazy" +></p> +<h2 id="二定时器管理">二、定时器管理 +</h2><h4 id="1概念">1、概念 +</h4><p>定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有<code>硬件定时器</code>和<code>软件定时器</code>之分:</p> +<p>1)<strong>硬件定时器</strong>是芯片本身提供的定时功能。<code>一般是由外部晶振(HSE)提供给芯片输入时钟</code>,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是<code>中断触发方式</code>。</p> +<p>2)<strong>软件定时器</strong>是由<code>操作系统提供的一类系统接口</code>,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。</p> +<p>RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即<code>定时数值必须是 OS Tick 的整数倍</code>,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。</p> +<h4 id="2rt-thread定时器介绍">2、RT-Thread定时器介绍 +</h4><p>RT-Thread 的定时器提供两类定时器机制:</p> +<p>第一类是<code>单次触发</code>定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。 +第二类是<code>周期触发</code>定时器,这类定时器会周期性的触发定时器事件,直到<code>用户手动的停止</code>,否则将永远持续执行下去。</p> +<p>另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 <code>HARD_TIMER </code>模式(硬件定时器模式)与<code> SOFT_TIMER</code> 模式(软件定时器模式),如下图。</p> +<p><img src="https://img-blog.csdnimg.cn/36887975b53c4dc684343c70a2f8db09.png" +loading="lazy" +></p> +<p>1)HARD_TIMER 模式:中断上下文</p> +<p>HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数<code>RT_TIMER_FLAG_HARD_TIMER</code>来指定。</p> +<p>在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:<code>执行时间应该尽量短,执行时不应导致当前上下文挂起、等待</code>。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。</p> +<p>2)SOFT_TIMER 模式:线程上下文</p> +<p>SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。</p> +<p>该模式被启用后,系统会在<code>初始化时创建一个 timer 线程</code>,然后 <code>SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行</code>。可以在初始化 / 创建定时器时使用参数 <code>RT_TIMER_FLAG_SOFT_TIMER </code>来指定设置 <code>SOFT_TIMER</code> 模式。</p> +<h4 id="3定时器源码分析">3、定时器源码分析 +</h4><p>1)RT-Thread OS 启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数</p> +<p><img src="https://img-blog.csdnimg.cn/0ee79523a62540a7a18155a0d9010365.png" +loading="lazy" +></p> +<p>2)rt_system_timer_init(硬件定时器初始化)</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_system_timer_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span><span class="c1">// 结构体数组,在初始化的时候只有一个元素,就是链表头,后期添加定时器,按定时器定时时间顺序进行顺序插入 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">rt_timer_list</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_list_init</span><span class="p">(</span><span class="n">rt_timer_list</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>3)rt_system_timer_thread_init(软件定时器初始化)</p> +<p><img src="https://img-blog.csdnimg.cn/68e5d39a7cf94149a474f05b0f370717.png" +loading="lazy" +></p> +<h4 id="4定时器工作机制">4、定时器工作机制 +</h4><p>下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的<code>全局变量</code>:</p> +<p>(1)当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);</p> +<p>(2)定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照<code>以超时时间排序</code>的方式<code>插入到 rt_timer_list 链表</code>中。</p> +<p>如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。</p> +<p><img src="https://img-blog.csdnimg.cn/bb6521cccf884694867fd32a5c76da27.png" +loading="lazy" +></p> +<p>而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),<code>50 个 tick 以后,rt_tick 从 20 增长到 70</code>,与 <code>Timer1 的 timeout 值相等</code>,这时会<code>触发与 Timer1 定时器相关联的超时函数</code>,同时将 <code>Timer1 从 rt_timer_list 链表上删除</code>。</p> +<p>同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。</p> +<p>如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 <code>timeout=rt_tick+300=330</code>, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:</p> +<p><img src="https://img-blog.csdnimg.cn/515005f47d5148848a7ea4fe883b6f39.png" +loading="lazy" +></p> +<h4 id="5定时器相关接口">5、定时器相关接口 +</h4><p>1)<strong>动态创建定时器</strong></p> +<p>动态创建声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>详细函数定义:</p> +<p><img src="https://img-blog.csdnimg.cn/87411b4f65564541a22792b8fc676ec1.png" +loading="lazy" +></p> +<p>查看flag定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_ONE_SHOT 0x0 </span><span class="c1">// 单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_PERIODIC 0x2 </span><span class="c1">// 周期性触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_FLAG_HARD_TIMER 0x0 </span><span class="c1">// 硬件定时器模式 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define RT_TIMER_FLAG_SOFT_TIMER 0x4 </span><span class="c1">// 软件定时器模式 +</span></span></span></code></pre></td></tr></table> +</div> +</div><blockquote> +<p>同时这里我们注意到<code>rt_timer_create</code>这个函数的返回值是<code>rt_timer_t</code>,通过查找定义可以发现该类型是通过typedef重命名的</p> +<p>也就是说<code>struct rt_timer</code> &lt;=&gt;<code>*rt_timer_t</code></p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">rt_timer</span> <span class="o">*</span><span class="kt">rt_timer_t</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面我们也可以详细看到rt_time这个结构体对定时器的一个详细描述</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">rt_object</span> <span class="n">parent</span><span class="p">;</span> <span class="cm">/**&lt; inherit from rt_object */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_list_t</span> <span class="n">row</span><span class="p">[</span><span class="n">RT_TIMER_SKIP_LIST_LEVEL</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout_func</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">);</span> <span class="cm">/**&lt; timeout function */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">;</span> <span class="cm">/**&lt; timeout function&#39;s parameter */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">init_tick</span><span class="p">;</span> <span class="cm">/**&lt; timer timeout tick */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout_tick</span><span class="p">;</span> <span class="cm">/**&lt; timeout tick */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2)<strong>删除定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rt_err_t rt_timer_delete(rt_timer_t timer); +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:返回操作系统的状态,成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/71ccf0b21d70422fa817b7f9ae7d6843.png" +loading="lazy" +></p> +<p>3)<strong>动态创建定时器演示</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里也可以看到,我们设置了一个名为tm_demo的定时器,设置超时时间为3s,同时flag我们是设置为周期定时和软件定时(flag设置详见上文flag定义 )。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写中断回调函数(超时函数) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 返回值结构图定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>4)<strong>开启定时器</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>函数返回值:成功返回0,失败返回1</p> +<p><img src="https://img-blog.csdnimg.cn/3542f82f0cc84f4f9c74b871c17753fe.png" +loading="lazy" +></p> +<p>5)实例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时我们在超时函数中编写代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此时回到串口查看,就可以发现tm_demo这个定时器已经被激活了,并且定时器的周期和超时时间也都发生改变,由于我们在上面设置的超时时间为3S,所以在串口显示会三秒打印一次信息</p> +<p>6)<strong>静态创建定时器</strong></p> +<p>函数定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">timeout</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">),</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">time</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_uint8_t</span> <span class="n">flag</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们看下<code>rt_timer_init</code>这个函数的返回值和参数</p> +<p>返回值:void</p> +<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">timer</td> +<td style="text-align:center">结构体指针类型</td> +</tr> +<tr> +<td style="text-align:center">name</td> +<td style="text-align:center">名字</td> +</tr> +<tr> +<td style="text-align:center">timeout</td> +<td style="text-align:center">超时回调函数指针</td> +</tr> +<tr> +<td style="text-align:center">parameter</td> +<td style="text-align:center">传递给超时回调函数的参数</td> +</tr> +<tr> +<td style="text-align:center">time</td> +<td style="text-align:center">定时器时间</td> +</tr> +<tr> +<td style="text-align:center">flag</td> +<td style="text-align:center">定时器标志</td> +</tr> +</tbody> +</table> +<p>7)<strong>脱离函数</strong>(静态创建时使用)</p> +<p>描述:当<code>静态创建</code>的定时器不需要在使用时,我们调用下面这个函数接口</p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_detach</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>返回值:成功返回0,失败返回1</p> +<p>8)<strong>定时器控制</strong></p> +<p>函数声明:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">rt_err_t</span> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="kt">rt_timer_t</span> <span class="n">timer</span><span class="p">,</span> <span class="kt">int</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>cmd命令定义查看</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_TIME 0x0 </span><span class="cm">/**&lt; set timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_TIME 0x1 </span><span class="cm">/**&lt; get timer control command */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_ONESHOT 0x2 </span><span class="cm">/**&lt; change timer to one shot */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_SET_PERIODIC 0x3 </span><span class="cm">/**&lt; change timer to periodic */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#define RT_TIMER_CTRL_GET_STATE 0x4 </span><span class="cm">/**&lt; get timer run state active or deactive*/</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://img-blog.csdnimg.cn/cb30a12c60e24f51a5ef081c296347bd.png" +loading="lazy" +></p> +<p>实例:</p> +<blockquote> +<p>查看终端数据,可以发现终端执行顺序为:打印一次tm的中断回调函数信息,然后打印三次tm2的信息。</p> +</blockquote> +<p><img src="https://img-blog.csdnimg.cn/67007c956ebd48478e44b9233abd8efe.png" +loading="lazy" +alt="在这里插入图片描述" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdevice.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtdbg.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">rt_timer_t</span> <span class="n">tm</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">rt_timer</span> <span class="n">tm2</span> <span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;tm_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">tm2_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">parameter</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">flags</span> <span class="o">==</span> <span class="mi">10</span><span class="p">)</span><span class="c1">// 当flags标志位位10时,设置单次触发 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_ONESHOT</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">rt_tick_t</span> <span class="n">timeout</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_control</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span> <span class="n">RT_TIMER_CTRL_SET_TIME</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">timeout</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;[%u]tm2_callback is running...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="nf">rt_tick_get</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 动态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">tm</span> <span class="o">=</span> <span class="nf">rt_timer_create</span><span class="p">(</span><span class="s">&#34;tm_demo&#34;</span><span class="p">,</span><span class="n">tm_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">tm</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_E</span><span class="p">(</span><span class="s">&#34;rt_timer_create faile...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">LOG_D</span><span class="p">(</span><span class="s">&#34;rt_timer_create successed...</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="n">tm</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 静态创建定时器 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">rt_timer_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">,</span><span class="s">&#34;tm2_demo&#34;</span><span class="p">,</span><span class="n">tm2_callback</span><span class="p">,</span><span class="nb">NULL</span><span class="p">,</span><span class="mi">3000</span><span class="p">,</span> <span class="n">RT_TIMER_FLAG_PERIODIC</span> <span class="o">|</span> <span class="n">RT_TIMER_FLAG_SOFT_TIMER</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tm2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="三高精度延时">三、高精度延时 +</h2><blockquote> +<p><code>注意:这个函数只支持低于1个OS Tick的延时,否则 SysTick会出现溢出而不能够获 得指定的延时时间</code></p> +</blockquote> +<ul> +<li>函数声明:<code>void rt_hw_us_delay(rt_uint32_t us);</code></li> +</ul> +<p><img src="https://img-blog.csdnimg.cn/43a92b7bdd884f18bf6ce522214cb520.png" +loading="lazy" +></p> +<ul> +<li>应用场景:应用于某些场景下对高精度延时有要求的情况下</li> +</ul>env工具学习https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/Thu, 12 May 2022 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadenv%E5%B7%A5%E5%85%B7%E5%AD%A6%E4%B9%A0/cover.jpg" alt="Featured image of post env工具学习" /><h4 id="一基础配置">一、基础配置 +</h4><p>1.首先需要下载git并配置好相应的环境变量</p> +<p>2.双击env,在setting中设置</p> +<p><img src="https://img-blog.csdnimg.cn/709a490d50c24945a2b06409d51b3209.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="在这里插入图片描述" +></p> +<p>这样就可以指定文件夹打开env工具了</p> +<h4 id="二基本命令学习">二、基本命令学习 +</h4><p>1.scons:编译</p> +<p><img src="https://img-blog.csdnimg.cn/976aba29a258481d9128f4b984f78139.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lul5pS-Xw==,size_20,color_FFFFFF,t_70,g_se,x_16" +loading="lazy" +alt="\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPYlwcMS-1649693722218)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220411234217601.png)\]" +></p> +<p><code>(1)scons:</code>编译并打印相关内部信息 +<code>(2)scons -c:</code>清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 +<code>(3)scons -s:</code>编译而不打印具体的内部命令 +<code>(4)scons --target=XXX:</code>使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons --target=iar +</span></span><span class="line"><span class="cl">scons --target=mdk4 +</span></span><span class="line"><span class="cl">scons --target=mdk5 +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>(5)scons -jN:</code>多线程编译目标,在多核计算机上可以使用此命令加快编译速度</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">scons -j4 //双核编译工程 +</span></span></code></pre></td></tr></table> +</div> +</div><p><!-- raw HTML omitted -->注意:一般不建议使用,容易将编译信息和错误混杂<!-- raw HTML omitted --> +<code>(6)scons --dist:</code>搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录 +2.指定编译器安装路径</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set RTT_CC=keil +</span></span><span class="line"><span class="cl">set RTT_EXEC_PATH=C:/Keilv5 +</span></span></code></pre></td></tr></table> +</div> +</div><p>3.menuconfig +打开菜单配置界面,可用户自定义模块</p> +<p>4.scons进阶学习 +scons内置函数</p> +<ul> +<li> +<p>GetCurrentDir(): +获取当前路径。</p> +</li> +<li> +<p>Glob(&rsquo;*.c&rsquo;): +获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。</p> +</li> +<li> +<p>GetDepend(macro): +该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。</p> +</li> +<li> +<p>Split(str): +将字符串 str 分割成一个列表 list。</p> +</li> +<li> +<p>DefineGroup(name, src, depend,**parameters): +这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 +<code>DefineGroup()</code> 函数的参数描述:</p> +</li> +</ul> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th style="text-align:center"><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>name</td> +<td style="text-align:center">Group 的名字</td> +</tr> +<tr> +<td>src</td> +<td style="text-align:center">Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件</td> +</tr> +<tr> +<td>depend</td> +<td style="text-align:center">Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现</td> +</tr> +<tr> +<td>parameters</td> +<td style="text-align:center">配置其他参数,可取值见下表,实际使用时不需要配置所有参数</td> +</tr> +</tbody> +</table> +<p>parameters可加入的参数:</p> +<table> +<thead> +<tr> +<th><!-- raw HTML omitted -->参数<!-- raw HTML omitted --></th> +<th><!-- raw HTML omitted -->描述<!-- raw HTML omitted --></th> +</tr> +</thead> +<tbody> +<tr> +<td>dirs</td> +<td>SConscript 文件路径</td> +</tr> +<tr> +<td>variant_dir</td> +<td>指定生成的目标文件的存放路径</td> +</tr> +<tr> +<td>duiplicate</td> +<td>设定是否拷贝或链接源文件到 variant_dir</td> +</tr> +</tbody> +</table> \ No newline at end of file diff --git a/tags/rt-thread/page/1/index.html b/tags/rt-thread/page/1/index.html new file mode 100644 index 000000000..4efb1264f --- /dev/null +++ b/tags/rt-thread/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/rt-thread/ + \ No newline at end of file diff --git a/tags/rt-thread/page/2/index.html b/tags/rt-thread/page/2/index.html new file mode 100644 index 000000000..e489d4d7a --- /dev/null +++ b/tags/rt-thread/page/2/index.html @@ -0,0 +1,57 @@ +Tag: RT-Thread - Pager 2 - kurisaW +

Tags

15 pages

RT-Thread

\ No newline at end of file diff --git a/tags/rt-thread/page/3/index.html b/tags/rt-thread/page/3/index.html new file mode 100644 index 000000000..f2e02eb6a --- /dev/null +++ b/tags/rt-thread/page/3/index.html @@ -0,0 +1,57 @@ +Tag: RT-Thread - Pager 3 - kurisaW +

Tags

15 pages

RT-Thread

\ No newline at end of file diff --git a/tags/rtduino/index.html b/tags/rtduino/index.html new file mode 100644 index 000000000..88bad55cf --- /dev/null +++ b/tags/rtduino/index.html @@ -0,0 +1,55 @@ +Tag: RTduino - kurisaW +

Tags

1 page

RTduino

\ No newline at end of file diff --git a/tags/rtduino/index.xml b/tags/rtduino/index.xml new file mode 100644 index 000000000..fb07b7a3f --- /dev/null +++ b/tags/rtduino/index.xml @@ -0,0 +1,1184 @@ +RTduino on kurisaWhttps://kurisaw.github.io/tags/rtduino/Recent content in RTduino on kurisaWHugo -- gohugo.ioenSun, 18 Feb 2024 00:00:00 +0000【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduinohttps://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/Sun, 18 Feb 2024 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/cover.jpg" alt="Featured image of post 【玩转RT-Thread】瑞萨HMI-Board使用vscode开发RTduino" /><h1 id="瑞萨hmi-board使用vscode开发rtduino结合ssd1306-oled">瑞萨HMI-Board使用vscode开发RTduino(结合ssd1306 oled) +</h1><hr> +<h2 id="1准备工作">1.准备工作 +</h2><p>软件环境:</p> +<ul> +<li><a class="link" href="https://github.com/RT-Thread/rt-thread" target="_blank" rel="noopener" +> RT-Thread 主仓代码(需下载至本地)</a></li> +<li>vscode</li> +<li>rt-thread env</li> +</ul> +<p>硬件环境:</p> +<ul> +<li>RA6M3-HMI-Board 开发板</li> +<li>0.96寸 ssd1306 oled 显示屏</li> +</ul> +<h2 id="2工程配置">2.工程配置 +</h2><p>首先我们需要准备好上述所需内容,在将 RT-Thread 源码拉取到本地后,进入如下目录:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要我们提前安装好 ENV 环境,具体细节请参考 <a class="link" href="https://docs.rtduino.com/#/zh/beginner/env?id=env%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba" target="_blank" rel="noopener" +>Env编译环境搭建</a> 。</p> +<p>鼠标右键打开 ENV 工具后,使用 <strong>menuconfig</strong> 命令打开可视化菜单,勾选上 <strong>RTduino</strong> 的使能项,保存并退出</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251.png" +width="1086" +height="392" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123170636251_hu8d0896b28c78ec2ba226d972cc9b9d66_18932_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123170636251" +class="gallery-image" +data-flex-grow="277" +data-flex-basis="664px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">RT-Thread Configuration +</span></span><span class="line"><span class="cl"> → Hardware Drivers Config +</span></span><span class="line"><span class="cl"> → Onboard Peripheral Drivers +</span></span><span class="line"><span class="cl"> <span class="o">[</span>*<span class="o">]</span> Compatible with Arduino Ecosystem <span class="o">(</span>RTduino<span class="o">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123171151275_hu896160409f1299a8e7f72313b1208e83_49774_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123171151275" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>此时我们可以注意到在使能该项后,系统会自动勾选上RTduino所需的软件包库及一些系统控制宏,同时我们还需要更新软件包进行下载(注意国内用户需要关闭代理后调用该命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pkgs --update +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们可以注意到在 bsp 根目录下生成了一个 packages 目录,并下载了我们所需的 RTduino 依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623.png" +width="1682" +height="768" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173108623_hu9818317fb8669572496764f5c1e90d0a_104325_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173108623" +class="gallery-image" +data-flex-grow="219" +data-flex-basis="525px" +></p> +<h2 id="3开始编译">3.开始编译 +</h2><p>打开 ENV ,同时执行如下命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ scons -j16 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831.png" +width="1920" +height="1004" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123173509831_hu4af38eccac0a3b38ba49909657b54b49_100762_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123173509831" +class="gallery-image" +data-flex-grow="191" +data-flex-basis="458px" +></p> +<p>在工程编译完成后会生成一个 <code>.elf</code>后缀的可执行文件,到这里工程的编译就顺利结束了。</p> +<h2 id="4vscode调试配置">4.vscode调试配置 +</h2><p>首先我们需要在 vscode 中安装 <code>Cortex-Debug</code> 插件,打开 vscode 扩展,搜索 <code>Cortex-Debug</code>并安装扩展:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123175244073_hu19dfc852061595e0b59627814afb4d72_250922_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123175244073" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接下来就是安装 <code>pyocd</code> 到本机了,当然也可以使用 python 进行安装,不过我们推荐使用 RT-Thread 官方提供的 pyocd,打开如下链接并下载到本地,这里下载最新版本即可:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">download link: https://github.com/RT-Thread-Studio/sdk-debugger-pyocd/releases +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是创建一份 debug 配置文件了,找到 vscode 左侧菜单栏的调试图标,点击 <code>create a launch.json file</code>:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889.png" +width="1385" +height="462" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123180230889_hu3c3d7ef8e7deed0551797e2cae34503d_41891_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123180230889" +class="gallery-image" +data-flex-grow="299" +data-flex-basis="719px" +></p> +<p>之后 vscode 会创建一份 <code>launch.json</code> 文件,我们需要替换文件内容为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// Use IntelliSense to learn about possible attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Hover to view descriptions of existing attributes. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.2.0&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;configurations&#34;</span><span class="p">:</span> <span class="p">[</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;HMI-Board&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;cwd&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceFolder}&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;executable&#34;</span><span class="p">:</span> <span class="s2">&#34;${workspaceRoot}/bsp/renesas/ra6m3-hmi-board/rtthread.elf&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;request&#34;</span><span class="p">:</span> <span class="s2">&#34;launch&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;cortex-debug&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;runToEntryPoint&#34;</span><span class="p">:</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;targetId&#34;</span><span class="p">:</span> <span class="s2">&#34;R7FA6M3AH&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;servertype&#34;</span><span class="p">:</span> <span class="s2">&#34;pyocd&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;serverpath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/compile/sdk-debugger-pyocd/pyocd.bat&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;armToolchainPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nt">&#34;gdbPath&#34;</span><span class="p">:</span> <span class="s2">&#34;D:/toolschain/gcc-arm-none-eabi-10-2020-q4-major-win32/bin/arm-none-eabi-gdb.exe&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<code>launch.json</code>文件中的部分参数需要根据具体位置配置</p> +<ul> +<li><code>serverpath</code>:这部分路径在前面所安装的 <code>sdk-debugger-pyocd</code>位置</li> +<li><code>armToolchainPath</code>:gcc 工具链,找不到位置的可以<a class="link" href="https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.exe?revision=9a4bce5a-7577-4b4f-910d-4585f55d35e8&amp;rev=9a4bce5a75774b4f910d4585f55d35e8&amp;hash=9770A44FEA9E9CDAC0DD9A009190CC8B" target="_blank" rel="noopener" +>点击此处下载</a></li> +<li><code>gdbPath</code></li> +</ul> +<p>在完成上述配置后就可以点击 <code>F5</code> 进行调试了,可能下载速度会比较慢,需要等待一会,调试成功效果如下:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123183906784_hu4193fbf261fb292b6d3393c5e365f285_122004_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123183906784" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>我们点击全速运行,并打开串口终端,可以看到系统启动后会自动打印 RTduino 线程信息:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932.png" +width="815" +height="536" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184032932_hue66132b98d0d39699465bd3964499c6e_27169_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184032932" +class="gallery-image" +data-flex-grow="152" +data-flex-basis="364px" +></p> +<p>到这里 RTduino 就已经成功运行在 RT-Thread 啦!</p> +<h2 id="5demo使用-rtduino-驱动-096寸-ssd1306-oled">5.demo:使用 RTduino 驱动 0.96寸 ssd1306 oled +</h2><p>在上面的环节中我们已经成功运行 RTduino 了,接下来我们将通过<code>RTduino</code>,并在<code>RT-Thread</code>中使用 <code>Arduino</code> 源码驱动一个 oled 屏幕。</p> +<p>我们接着回到 ENV 中,使用 <code>menuconfig</code>命令打开菜单,同时使用 <code>shift + /</code>打开搜索界面,并且输入:<code>ssd1306</code>关键字后回车搜索,在出现的页面我们使用键盘的方向键向下翻找,找到 <code>Adafruit SSD1306</code>对应的 <code>2</code>选项,进入点击 <code>y</code> 使能:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184834403_hue981b9fca4b8353c1c66949c5f753232_77378_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184834403" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394.png" +width="1920" +height="946" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123184930394_hu3aeac499ced8b050c8858e3a276fb87c_46269_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123184930394" +class="gallery-image" +data-flex-grow="202" +data-flex-basis="487px" +></p> +<p>这样我们就成功把 <code>Adafruit SSD1306</code> 示例库下载到本地了,同时还有一下依赖库:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453.png" +width="1720" +height="772" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123185120453_hu43bb075284a1598afec893f4245d907b_263089_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123185120453" +class="gallery-image" +data-flex-grow="222" +data-flex-basis="534px" +></p> +<p>我们找到路径:<code>rt-thread\bsp\renesas\ra6m3-hmi-board\packages\Adafruit-SSD1306-latest\examples\ssd1306_128x64_i2c</code>,可以看到该文件夹下有一个<code>ssd1306_128x64_i2c.ino</code>文件,这就是 Arduino 的工程文件,我们复制该文件内容到如下路径下的<code>arduino_main.cpp</code>文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> rt-thread<span class="se">\b</span>sp<span class="se">\r</span>enesas<span class="se">\r</span>a6m3-hmi-board<span class="se">\b</span>oard<span class="se">\r</span>tduino<span class="se">\a</span>rduino_main.cpp +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span><span class="lnt">267 +</span><span class="lnt">268 +</span><span class="lnt">269 +</span><span class="lnt">270 +</span><span class="lnt">271 +</span><span class="lnt">272 +</span><span class="lnt">273 +</span><span class="lnt">274 +</span><span class="lnt">275 +</span><span class="lnt">276 +</span><span class="lnt">277 +</span><span class="lnt">278 +</span><span class="lnt">279 +</span><span class="lnt">280 +</span><span class="lnt">281 +</span><span class="lnt">282 +</span><span class="lnt">283 +</span><span class="lnt">284 +</span><span class="lnt">285 +</span><span class="lnt">286 +</span><span class="lnt">287 +</span><span class="lnt">288 +</span><span class="lnt">289 +</span><span class="lnt">290 +</span><span class="lnt">291 +</span><span class="lnt">292 +</span><span class="lnt">293 +</span><span class="lnt">294 +</span><span class="lnt">295 +</span><span class="lnt">296 +</span><span class="lnt">297 +</span><span class="lnt">298 +</span><span class="lnt">299 +</span><span class="lnt">300 +</span><span class="lnt">301 +</span><span class="lnt">302 +</span><span class="lnt">303 +</span><span class="lnt">304 +</span><span class="lnt">305 +</span><span class="lnt">306 +</span><span class="lnt">307 +</span><span class="lnt">308 +</span><span class="lnt">309 +</span><span class="lnt">310 +</span><span class="lnt">311 +</span><span class="lnt">312 +</span><span class="lnt">313 +</span><span class="lnt">314 +</span><span class="lnt">315 +</span><span class="lnt">316 +</span><span class="lnt">317 +</span><span class="lnt">318 +</span><span class="lnt">319 +</span><span class="lnt">320 +</span><span class="lnt">321 +</span><span class="lnt">322 +</span><span class="lnt">323 +</span><span class="lnt">324 +</span><span class="lnt">325 +</span><span class="lnt">326 +</span><span class="lnt">327 +</span><span class="lnt">328 +</span><span class="lnt">329 +</span><span class="lnt">330 +</span><span class="lnt">331 +</span><span class="lnt">332 +</span><span class="lnt">333 +</span><span class="lnt">334 +</span><span class="lnt">335 +</span><span class="lnt">336 +</span><span class="lnt">337 +</span><span class="lnt">338 +</span><span class="lnt">339 +</span><span class="lnt">340 +</span><span class="lnt">341 +</span><span class="lnt">342 +</span><span class="lnt">343 +</span><span class="lnt">344 +</span><span class="lnt">345 +</span><span class="lnt">346 +</span><span class="lnt">347 +</span><span class="lnt">348 +</span><span class="lnt">349 +</span><span class="lnt">350 +</span><span class="lnt">351 +</span><span class="lnt">352 +</span><span class="lnt">353 +</span><span class="lnt">354 +</span><span class="lnt">355 +</span><span class="lnt">356 +</span><span class="lnt">357 +</span><span class="lnt">358 +</span><span class="lnt">359 +</span><span class="lnt">360 +</span><span class="lnt">361 +</span><span class="lnt">362 +</span><span class="lnt">363 +</span><span class="lnt">364 +</span><span class="lnt">365 +</span><span class="lnt">366 +</span><span class="lnt">367 +</span><span class="lnt">368 +</span><span class="lnt">369 +</span><span class="lnt">370 +</span><span class="lnt">371 +</span><span class="lnt">372 +</span><span class="lnt">373 +</span><span class="lnt">374 +</span><span class="lnt">375 +</span><span class="lnt">376 +</span><span class="lnt">377 +</span><span class="lnt">378 +</span><span class="lnt">379 +</span><span class="lnt">380 +</span><span class="lnt">381 +</span><span class="lnt">382 +</span><span class="lnt">383 +</span><span class="lnt">384 +</span><span class="lnt">385 +</span><span class="lnt">386 +</span><span class="lnt">387 +</span><span class="lnt">388 +</span><span class="lnt">389 +</span><span class="lnt">390 +</span><span class="lnt">391 +</span><span class="lnt">392 +</span><span class="lnt">393 +</span><span class="lnt">394 +</span><span class="lnt">395 +</span><span class="lnt">396 +</span><span class="lnt">397 +</span><span class="lnt">398 +</span><span class="lnt">399 +</span><span class="lnt">400 +</span><span class="lnt">401 +</span><span class="lnt">402 +</span><span class="lnt">403 +</span><span class="lnt">404 +</span><span class="lnt">405 +</span><span class="lnt">406 +</span><span class="lnt">407 +</span><span class="lnt">408 +</span><span class="lnt">409 +</span><span class="lnt">410 +</span><span class="lnt">411 +</span><span class="lnt">412 +</span><span class="lnt">413 +</span><span class="lnt">414 +</span><span class="lnt">415 +</span><span class="lnt">416 +</span><span class="lnt">417 +</span><span class="lnt">418 +</span><span class="lnt">419 +</span><span class="lnt">420 +</span><span class="lnt">421 +</span><span class="lnt">422 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/* +</span></span><span class="line"><span class="cl"> * Copyright <span class="o">(</span>c<span class="o">)</span> 2006-2023, RT-Thread Development Team +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * SPDX-License-Identifier: Apache-2.0 +</span></span><span class="line"><span class="cl"> * +</span></span><span class="line"><span class="cl"> * Change Logs: +</span></span><span class="line"><span class="cl"> * Date Author Notes +</span></span><span class="line"><span class="cl"> * 2023-10-28 Wangyuqiang first version +</span></span><span class="line"><span class="cl"> */ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Arduino.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;SPI.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Wire.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_GFX.h&gt;</span> +</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;Adafruit_SSD1306.h&gt;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_WIDTH 128 // OLED display width, in pixels</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_HEIGHT 64 // OLED display height, in pixels</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">// Declaration <span class="k">for</span> an SSD1306 display connected to I2C <span class="o">(</span>SDA, SCL pins<span class="o">)</span> +</span></span><span class="line"><span class="cl">// The pins <span class="k">for</span> I2C are defined by the Wire-library. +</span></span><span class="line"><span class="cl">// On an arduino UNO: A4<span class="o">(</span>SDA<span class="o">)</span>, A5<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino MEGA 2560: 20<span class="o">(</span>SDA<span class="o">)</span>, 21<span class="o">(</span>SCL<span class="o">)</span> +</span></span><span class="line"><span class="cl">// On an arduino LEONARDO: 2<span class="o">(</span>SDA<span class="o">)</span>, 3<span class="o">(</span>SCL<span class="o">)</span>, ... +</span></span><span class="line"><span class="cl"><span class="c1">#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define SCREEN_ADDRESS 0x3C ///&lt; See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32</span> +</span></span><span class="line"><span class="cl">Adafruit_SSD1306 display<span class="o">(</span>SCREEN_WIDTH, SCREEN_HEIGHT, <span class="p">&amp;</span>Wire, OLED_RESET<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define NUMFLAKES 10 // Number of snowflakes in the animation example</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_HEIGHT 16</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define LOGO_WIDTH 16</span> +</span></span><span class="line"><span class="cl">static const unsigned char PROGMEM logo_bmp<span class="o">[]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="o">{</span> 0b00000000, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000001, 0b11000000, +</span></span><span class="line"><span class="cl"> 0b00000011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11110011, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b11111110, 0b11111000, +</span></span><span class="line"><span class="cl"> 0b01111110, 0b11111111, +</span></span><span class="line"><span class="cl"> 0b00110011, 0b10011111, +</span></span><span class="line"><span class="cl"> 0b00011111, 0b11111100, +</span></span><span class="line"><span class="cl"> 0b00001101, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00011011, 0b10100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11100000, +</span></span><span class="line"><span class="cl"> 0b00111111, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01111100, 0b11110000, +</span></span><span class="line"><span class="cl"> 0b01110000, 0b01110000, +</span></span><span class="line"><span class="cl"> 0b00000000, 0b00110000 <span class="o">}</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void setup<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.begin<span class="o">(</span>115200<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // <span class="nv">SSD1306_SWITCHCAPVCC</span> <span class="o">=</span> generate display voltage from 3.3V internally +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span>!display.begin<span class="o">(</span>SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS<span class="o">))</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;SSD1306 allocation failed&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span><span class="p">;</span> // Don<span class="s1">&#39;t proceed, loop forever +</span></span></span><span class="line"><span class="cl"><span class="s1"> } +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show initial display buffer contents on the screen -- +</span></span></span><span class="line"><span class="cl"><span class="s1"> // the library initializes this with an Adafruit splash screen. +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); // Pause for 2 seconds +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Clear the buffer +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.clearDisplay(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Draw a single pixel in white +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.drawPixel(10, 10, SSD1306_WHITE); +</span></span></span><span class="line"><span class="cl"><span class="s1"> +</span></span></span><span class="line"><span class="cl"><span class="s1"> // Show the display buffer on the screen. You MUST call display() after +</span></span></span><span class="line"><span class="cl"><span class="s1"> // drawing commands to make them visible on screen! +</span></span></span><span class="line"><span class="cl"><span class="s1"> display.display(); +</span></span></span><span class="line"><span class="cl"><span class="s1"> delay(2000); +</span></span></span><span class="line"><span class="cl"><span class="s1"> // display.display() is NOT necessary after every single drawing command, +</span></span></span><span class="line"><span class="cl"><span class="s1"> // unless that&#39;</span>s what you want...rather, you can batch up a bunch of +</span></span><span class="line"><span class="cl"> // drawing operations and <span class="k">then</span> update the screen all at once by calling +</span></span><span class="line"><span class="cl"> // display.display<span class="o">()</span>. These examples demonstrate both approaches... +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawline<span class="o">()</span><span class="p">;</span> // Draw many lines +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillrect<span class="o">()</span><span class="p">;</span> // Draw rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillcircle<span class="o">()</span><span class="p">;</span> // Draw circles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfillroundrect<span class="o">()</span><span class="p">;</span> // Draw rounded rectangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawtriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>outlines<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testfilltriangle<span class="o">()</span><span class="p">;</span> // Draw triangles <span class="o">(</span>filled<span class="o">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawchar<span class="o">()</span><span class="p">;</span> // Draw characters of the default font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawstyles<span class="o">()</span><span class="p">;</span> // Draw <span class="s1">&#39;stylized&#39;</span> characters +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testscrolltext<span class="o">()</span><span class="p">;</span> // Draw scrolling text +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testdrawbitmap<span class="o">()</span><span class="p">;</span> // Draw a small bitmap image +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Invert and restore display, pausing in-between +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.invertDisplay<span class="o">(</span><span class="nb">false</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> testanimate<span class="o">(</span>logo_bmp, LOGO_WIDTH, LOGO_HEIGHT<span class="o">)</span><span class="p">;</span> // Animate bitmaps +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void loop<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawline<span class="o">()</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int16_t i<span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn line +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, 0, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>0, display.height<span class="o">()</span>-1, display.width<span class="o">()</span>-1, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.width<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, i, 0, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>display.height<span class="o">()</span>-1<span class="p">;</span> i&gt;<span class="o">=</span>0<span class="p">;</span> i-<span class="o">=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, display.height<span class="o">()</span>-1, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>250<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, 0, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.width<span class="o">()</span><span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>4<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawLine<span class="o">(</span>display.width<span class="o">()</span>-1, 0, i, display.height<span class="o">()</span>-1, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> <span class="m">2</span> seconds +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so rectangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-i*2, display.height<span class="o">()</span>-i*2, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn rectangle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawCircle<span class="o">(</span>display.width<span class="o">()</span>/2, display.height<span class="o">()</span>/2, i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillcircle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>3<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so circles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillCircle<span class="o">(</span>display.width<span class="o">()</span> / 2, display.height<span class="o">()</span> / 2, i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Update screen with each newly-drawn circle +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfillroundrect<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;display.height<span class="o">()</span>/2-2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>2<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so round-rects alternate white/black +</span></span><span class="line"><span class="cl"> display.fillRoundRect<span class="o">(</span>i, i, display.width<span class="o">()</span>-2*i, display.height<span class="o">()</span>-2*i, +</span></span><span class="line"><span class="cl"> display.height<span class="o">()</span>/4, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawtriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> <span class="nv">i</span><span class="o">+=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testfilltriangle<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>max<span class="o">(</span>display.width<span class="o">()</span>,display.height<span class="o">())</span>/2<span class="p">;</span> i&gt;0<span class="p">;</span> i-<span class="o">=</span>5<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // The INVERSE color is used so triangles alternate white/black +</span></span><span class="line"><span class="cl"> display.fillTriangle<span class="o">(</span> +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2 , display.height<span class="o">()</span>/2-i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2-i, display.height<span class="o">()</span>/2+i, +</span></span><span class="line"><span class="cl"> display.width<span class="o">()</span>/2+i, display.height<span class="o">()</span>/2+i, SSD1306_INVERSE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawchar<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0, 0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.cp437<span class="o">(</span><span class="nb">true</span><span class="o">)</span><span class="p">;</span> // Use full <span class="m">256</span> char <span class="s1">&#39;Code Page 437&#39;</span> font +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Not all the characters will fit on the display. This is normal. +</span></span><span class="line"><span class="cl"> // Library will draw what it can and the rest will be clipped. +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span>int16_t <span class="nv">i</span><span class="o">=</span>0<span class="p">;</span> i&lt;256<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="o">(</span><span class="nv">i</span> <span class="o">==</span> <span class="s1">&#39;\n&#39;</span><span class="o">)</span> display.write<span class="o">(</span><span class="s1">&#39; &#39;</span><span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> display.write<span class="o">(</span>i<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawstyles<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>1<span class="o">)</span><span class="p">;</span> // Normal 1:1 pixel scale +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw white text +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>0,0<span class="o">)</span><span class="p">;</span> // Start at top-left corner +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_BLACK, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> // Draw <span class="s1">&#39;inverse&#39;</span> text +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>3.141592<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;0x&#34;</span><span class="o">))</span><span class="p">;</span> display.println<span class="o">(</span>0xDEADBEEF, HEX<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testscrolltext<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.setTextSize<span class="o">(</span>2<span class="o">)</span><span class="p">;</span> // Draw 2X-scale text +</span></span><span class="line"><span class="cl"> display.setTextColor<span class="o">(</span>SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.setCursor<span class="o">(</span>10, 0<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.println<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;scroll&#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show initial text +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>100<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Scroll in various directions, pausing in-between: +</span></span><span class="line"><span class="cl"> display.startscrollright<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrollleft<span class="o">(</span>0x00, 0x0F<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagright<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.startscrolldiagleft<span class="o">(</span>0x00, 0x07<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>2000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.stopscroll<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testdrawbitmap<span class="o">(</span>void<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span> +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.width<span class="o">()</span> - LOGO_WIDTH <span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> <span class="o">(</span>display.height<span class="o">()</span> - LOGO_HEIGHT<span class="o">)</span> / 2, +</span></span><span class="line"><span class="cl"> logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>1000<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#define XPOS 0 // Indexes into the &#39;icons&#39; array in function below</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define YPOS 1</span> +</span></span><span class="line"><span class="cl"><span class="c1">#define DELTAY 2</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">void testanimate<span class="o">(</span>const uint8_t *bitmap, uint8_t w, uint8_t h<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> int8_t f, icons<span class="o">[</span>NUMFLAKES<span class="o">][</span>3<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Initialize <span class="s1">&#39;snowflake&#39;</span> positions +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34;x: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; y: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.print<span class="o">(</span>F<span class="o">(</span><span class="s2">&#34; dy: &#34;</span><span class="o">))</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> Serial.println<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span>, DEC<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="p">;;</span><span class="o">)</span> <span class="o">{</span> // Loop forever... +</span></span><span class="line"><span class="cl"> display.clearDisplay<span class="o">()</span><span class="p">;</span> // Clear the display buffer +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Draw each snowflake: +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> display.drawBitmap<span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span>, icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span>, bitmap, w, h, SSD1306_WHITE<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> display.display<span class="o">()</span><span class="p">;</span> // Show the display buffer on the screen +</span></span><span class="line"><span class="cl"> delay<span class="o">(</span>200<span class="o">)</span><span class="p">;</span> // Pause <span class="k">for</span> 1/10 second +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> // Then update coordinates of each flake... +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="o">(</span><span class="nv">f</span><span class="o">=</span>0<span class="p">;</span> f&lt; NUMFLAKES<span class="p">;</span> f++<span class="o">)</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> +<span class="o">=</span> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> // If snowflake is off the bottom of the screen... +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">(</span>icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> &gt;<span class="o">=</span> display.height<span class="o">())</span> <span class="o">{</span> +</span></span><span class="line"><span class="cl"> // Reinitialize to a random position, just off the top +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>XPOS<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span><span class="m">1</span> - LOGO_WIDTH, display.width<span class="o">())</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>YPOS<span class="o">]</span> <span class="o">=</span> -LOGO_HEIGHT<span class="p">;</span> +</span></span><span class="line"><span class="cl"> icons<span class="o">[</span>f<span class="o">][</span>DELTAY<span class="o">]</span> <span class="o">=</span> random<span class="o">(</span>1, 6<span class="o">)</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">}</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在此示例中有几点注意事项:</p> +<ul> +<li>在每一份添加的示例工程中,我们都必须要包含头文件 <code>#include &lt;Arduino.h&gt;</code></li> +<li>由于我的这款 ssd1306 oled 显示屏是 i2c 驱动,i2c地址为 <code>0x3c</code>,所以对应示例工程中的 <code>SCREEN_ADDRESS</code>需要修改为 <code>0X3C</code></li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061.png" +width="533" +height="143" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190157061_hu8a3d8543fb6e60812177c0c00e8cafca_20743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190157061" +class="gallery-image" +data-flex-grow="372" +data-flex-basis="894px" +></p> +<ul> +<li>由于 Arduino 代码风格是一般不会添加函数声明的,需要我们手动添加一遍</li> +</ul> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607.png" +width="1920" +height="1030" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123190348607_huf9270c96311cd21b6f20f26e38cf62e0_256139_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123190348607" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>接着我们继续编译工程源码,同时准备接线,由于在这份示例工程中默认使用的是 RTduino 默认的 i2c 设备(具体可查看文件:pins_arduino.h),而这份 bsp 对接 RTduino 默认为 RT-Thread 的软件模拟 i2c0,其对应引脚为:</p> +<table> +<thead> +<tr> +<th style="text-align:center">pin</th> +<th style="text-align:center">func</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">P203</td> +<td style="text-align:center">i2c0-sda</td> +</tr> +<tr> +<td style="text-align:center">P202</td> +<td style="text-align:center">i2c0-scl</td> +</tr> +<tr> +<td style="text-align:center">VCC</td> +<td style="text-align:center">vcc</td> +</tr> +<tr> +<td style="text-align:center">GND</td> +<td style="text-align:center">gnd</td> +</tr> +</tbody> +</table> +<p>接着我们启动调试,在等待下载后可以看到系统初始化会同时启动 RT-Thread main线程和 RTduino线程</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695.png" +width="813" +height="431" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/image-20240123191534695_huded9533eaa475083c852bef1354ae06b_23008_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="image-20240123191534695" +class="gallery-image" +data-flex-grow="188" +data-flex-basis="452px" +></p> +<p>查看demo:</p> +<p><img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo.gif" +width="1280" +height="720" +srcset="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_480x0_resize_box_1.gif 480w, https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-thread%E7%91%9E%E8%90%A8hmi-board%E4%BD%BF%E7%94%A8vscode%E5%BC%80%E5%8F%91rtduino/figures/demo_hu55faf0cb12b470d4d703d4639e500e16_14061071_1024x0_resize_box_1.gif 1024w" +loading="lazy" +alt="demo" +class="gallery-image" +data-flex-grow="177" +data-flex-basis="426px" +></p> \ No newline at end of file diff --git a/tags/rtduino/page/1/index.html b/tags/rtduino/page/1/index.html new file mode 100644 index 000000000..e13fc6e84 --- /dev/null +++ b/tags/rtduino/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/rtduino/ + \ No newline at end of file diff --git "a/tags/sal\345\245\227\346\216\245\345\255\227/index.html" "b/tags/sal\345\245\227\346\216\245\345\255\227/index.html" new file mode 100644 index 000000000..f1e984a2b --- /dev/null +++ "b/tags/sal\345\245\227\346\216\245\345\255\227/index.html" @@ -0,0 +1,55 @@ +Tag: SAL套接字 - kurisaW +

Tags

1 page

SAL套接字

\ No newline at end of file diff --git "a/tags/sal\345\245\227\346\216\245\345\255\227/index.xml" "b/tags/sal\345\245\227\346\216\245\345\255\227/index.xml" new file mode 100644 index 000000000..8fe29d48d --- /dev/null +++ "b/tags/sal\345\245\227\346\216\245\345\255\227/index.xml" @@ -0,0 +1,830 @@ +SAL套接字 on kurisaWhttps://kurisaw.github.io/tags/sal%E5%A5%97%E6%8E%A5%E5%AD%97/Recent content in SAL套接字 on kurisaWHugo -- gohugo.ioenWed, 12 Apr 2023 00:00:00 +0000RT-Thread网络框架:BSD网络接口&SAL套接字抽象层https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/Wed, 12 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/<img src="https://kurisaw.github.io/p/%E7%8E%A9%E8%BD%ACrt-threadrt-thread%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6bsd%E7%BD%91%E7%BB%9C%E6%8E%A5%E5%8F%A3sal%E5%A5%97%E6%8E%A5%E5%AD%97%E6%8A%BD%E8%B1%A1%E5%B1%82/cover.jpg" alt="Featured image of post RT-Thread网络框架:BSD网络接口&SAL套接字抽象层" /><h1 id="rt-thread网络框架bsd网络接口sal套接字抽象层">RT-Thread网络框架:BSD网络接口&amp;SAL套接字抽象层 +</h1><hr> +<h2 id="基础知识">基础知识 +</h2><h4 id="1tcp与udp的区别">1.TCP与UDP的区别 +</h4><p>TCP(Transmission Control Protocol 传输控制协议):是一种面向连接、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。</p> +<p>UDP(User Datagram Protocol 用户数据报协议):是OSI(Open System Interconnection 开放式系统互联):参考模型中的一种无连接的传输层协议,提供面向事务的简单不可靠传送服务。</p> +<p>OSI七层模型和TCP/IP四层模型详解请看<a class="link" href="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/" target="_blank" rel="noopener" +>此处</a></p> +<p>区别:</p> +<ul> +<li>TCP提供的是面向连接、可靠的数据流传输;UDP提供的是非面向连接、不可靠的数据流传输。</li> +<li>TCP提供可靠的服务,通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达;UDP尽最大努力交付,但不保证可靠性。</li> +<li>TCP面向字节流;UDP面向报文。</li> +<li>TCP仅支持点对点连接;UDP支持一对一、一对多、多对多的交互通信。</li> +<li>TCP最低开销20字节(首部开销);UDP首部开销8字节,开销小。</li> +<li>TCP的逻辑同性能信道是全双工的可靠信道;UDP的逻辑通信信道是不可靠信道。</li> +</ul> +<h4 id="2tcp编程-服务端配置过程">2.TCP编程 服务端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket类上</li> +<li><code>listen():</code>开启监听</li> +<li><code>accept():</code>接收来自客户端的连接</li> +<li>收发数据:<code>send()、recv()、read()、write()</code></li> +<li>关闭网络连接</li> +<li>关闭监听</li> +</ul> +<h4 id="3tcp编程-客户端配置过程">3.TCP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li><code>recvfrom():</code>循环接收数据</li> +<li>关闭网络连接</li> +</ul> +<h4 id="4udp编程-客户端配置过程">4.UDP编程 客户端配置过程 +</h4><ul> +<li><code>socket():</code>创建一个socket</li> +<li><code>setsockopt():</code>设置socket属性,可选</li> +<li><code>bind():</code>绑定IP地址、端口等信息到socket上</li> +<li>设置对方的IP地址和端口等属性</li> +<li><code>sendto():</code>发送数据</li> +<li>关闭网络连接</li> +</ul> +<h2 id="sal套接字抽象层">SAL套接字抽象层 +</h2><p>SAL(套接字抽象层)是RT-Thread官方为避免系统对单一网络协议栈的依赖,同时也为适配更多网络协议栈类型而提供的一套网络组件,该组件主要完成对不同网络协议栈或网络实现接口的抽象并对上层一共一组标准BSD Socket API,这样开发者只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大提高了系统的兼容性。</p> +<h4 id="1sal组件主要功能特点">1.SAL组件主要功能特点: +</h4><ul> +<li>抽象、统一多种网络协议栈接口</li> +<li>提供Socket层面的TLS加密传输特性</li> +<li>支持标准 BSD Socket API</li> +<li>统一的FD管理,便于使用read/write poll/select来操作网络功能</li> +</ul> +<h4 id="2sal网络框架">2.SAL网络框架 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304111315461.png" +loading="lazy" +alt="image-20230411131524312" +></p> +<ul> +<li>应用层:提供一套标准BSD Socket API<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。如socket、connect等函数,用于系统中大部分网络开发应用。</li> +<li>SAL套接字抽象层:RT-Thread通过该层能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv等。</li> +<li>netdev网卡层:主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过netdev网卡层,用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。</li> +<li>协议栈层:该层包括几种常用的TCP/IP协议栈,如嵌入式开发中常用的<strong>轻型TCP/IP协议栈lwip</strong>以及RT-Thread自主研发的AT Socket网络功能实现等。</li> +</ul> +<h4 id="3工作原理">3.工作原理 +</h4><p>SAL组件工作原理的介绍主要分为如下两部分:</p> +<ul> +<li>多协议栈接入与接口函数统一抽象功能</li> +<li>SAL TLS加密传输功能</li> +</ul> +<h4 id="4多协议接入与接口函数统一抽象功能">4.多协议接入与接口函数统一抽象功能 +</h4><p>由于不同协议栈或网络功能的实现,其网络接口的名称各有不同,已连接函数为例,lwip协议栈中接口名称为lwip_connect,而AT Socket网络实现接口为at_connect。通过SAL组件可以完成对不同协议栈或网络实现接口的抽象和统一,组件再socket创建时通过判断传入的协议簇(domain)类型来判断使用的协议栈或网络功能。</p> +<p>目前RT-Thread SAL组件支持的协议栈或网络实现类型有:LWIP协议栈(AT_INET)、AT Socket协议栈(AF_AT)、WIZnet硬件 TCP/IP协议栈(AT_WIZ)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>为了动态适配不同协议栈或网络实现的接入,SAL组件中对于每个协议栈或者网络实现提供两种协议类型匹配方式:<strong>主协议簇类型和次协议簇类型</strong>,在socket创建之初收i西安判断传入协议簇类型是否存在已经支持的主协议类型,如果是则使用对应协议栈或网络实现,如果不是则判断次协议簇类型是否支持。</p> +<p>具体而言,主协议簇类型是指一个协议簇的最基本类型,例如 IPv4 或 IPv6。次协议簇类型则是在主协议簇类型的基础上进行扩展或增强,例如 TCP 或 UDP 协议。主协议簇类型可以被多个次协议簇类型所支持,但一个次协议簇类型只能属于一个主协议簇类型。</p> +<p>目前系统支持协议簇类型如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">LWIP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">AT</span> <span class="n">Socket协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_AT</span><span class="err">、</span><span class="n">sec_family</span> <span class="o">=</span> <span class="n">AF_INET</span> +</span></span><span class="line"><span class="cl"><span class="n">WIZnet硬件</span> <span class="n">TCP</span><span class="o">/</span><span class="n">IP协议栈</span><span class="err">:</span><span class="n">family</span> <span class="o">=</span> <span class="n">AF_WIZ</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>SAL组件的主要作用是统一BSD Socket API接口,我们以官方示例对SAL组件函数进行调用方式的实现:</p> +<ul> +<li>connect: SAL组件对外提供的抽象的BSD Socket API,用于统一fd管理;</li> +<li>sal_connect: SAL组件中connect实现函数,用于调用底层协议栈注册的operation函数;</li> +<li>lwip_connect: 底层协议栈提供的connect连接函数,在网卡初始化完成时注册到SAL组件中,最终调用的操作函数</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* SAL 组件为应用层提供的标准 BSD Socket API */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取 SAL 套接字描述符 */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">socket</span> <span class="o">=</span> <span class="nf">dfs_net_getsocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过 SAL 套接字描述符执行 sal_connect 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* SAL 组件抽象函数接口实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sal_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sal_proto_family</span> <span class="o">*</span><span class="n">pf</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查 SAL socket 结构体是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_SOCKET_OBJ_GET</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">socket</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 网络连接状态是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_IS_COMMONICABLE</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 检查当前 socket 对应的底层 operation 函数是否正常 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">SAL_NETDEV_SOCKETOPS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">netdev</span><span class="p">,</span> <span class="n">pf</span><span class="p">,</span> <span class="n">connect</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 执行底层注册的 connect operation 函数 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="n">pf</span><span class="o">-&gt;</span><span class="n">skt_ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_TLS +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nf">SAL_SOCKOPS_PROTO_TLS_VALID</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">connect</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">proto_tls</span><span class="o">-&gt;</span><span class="n">ops</span><span class="o">-&gt;</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="o">-&gt;</span><span class="n">user_data_tls</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* lwIP 协议栈函数底层 connect 函数实现 */</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">lwip_connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">socket</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5sal-tls加密传输功能">5.SAL TLS加密传输功能 +</h4><p>在TCP、UDP等协议数据传输时,由于数据包是明文的,所以很可能被拦截,甚至被解析出数据,为了保证网络传输的安全性,需要用户在应用层和传输层之间添加SSL/TLS协议。</p> +<p>TLS(Transport Layer Security,传输层安全协议)是建立在传输层TCP协议之上的协议,其前身是SSL(Secure Socket Layer,安全套接字层),主要作用是将应用层的报文进行非对称加密后再由TCP协议进行传输,实现了数据的加密安全交互。<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> +<p>对于通过的加密方式,需要使用其指定的加密接口和流程进行加密,而SAL TLS功能的主要作用是<strong>提供Socket层面的TLS加密传输特性,抽象多种TLS处理方式,提供统一的接口用于完成TLS数据交互。</strong></p> +<p>使用流程:</p> +<ul> +<li>配置开启任意网络协议栈支持(如LWIP协议栈)</li> +<li>配置开启MbedTLS软件包(目前仅支持MbedTLS类型加密方式)</li> +<li>配置开启SAL_TLS功能支持</li> +</ul> +<p>配置完成后,需要在socket创建时传入的<code>potocol</code>类型是使用<strong>PROTOCOL_TLS</strong>或者<strong>PROTOCOL_DTLS</strong>,即可使用标准BSD Socket API接口,完成TLS连接的建立和数据的收发。</p> +<p>示例如下,参考RT-Threda文档中心:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/socket.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdb.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* RT-Thread 官网,支持 TLS 功能 */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_HOST &#34;www.rt-thread.org&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_PORT 443 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SAL_TLS_BUFSZ 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">send_data</span> <span class="o">=</span> <span class="s">&#34;GET /download/rt-thread.txt HTTP/1.1</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Host: www.rt-thread.org</span><span class="se">\r\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;User-Agent: rtthread/4.0.1 rtt</span><span class="se">\r\n\r\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">sal_tls_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">recv_data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sock</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */</span> +</span></span><span class="line"><span class="cl"> <span class="n">host</span> <span class="o">=</span> <span class="nf">gethostbyname</span><span class="p">(</span><span class="n">SAL_TLS_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">recv_data</span> <span class="o">=</span> <span class="nf">rt_calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;No memory</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sock</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="n">PROTOCOL_TLS</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket error</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SAL_TLS_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="k">struct</span> <span class="n">in_addr</span> <span class="o">*</span><span class="p">)</span><span class="n">host</span><span class="o">-&gt;</span><span class="n">h_addr</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Connect fail!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 发送数据到 socket 连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">send_data</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">send_data</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;send error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 接收并打印响应的数据,使用加密数据传输 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">bytes_received</span> <span class="o">=</span> <span class="nf">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">,</span> <span class="n">SAL_TLS_BUFSZ</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bytes_received</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;received error,close the socket.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">__exit</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;recv data:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes_received</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;%c&#34;</span><span class="p">,</span> <span class="n">recv_data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">__exit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">recv_data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_free</span><span class="p">(</span><span class="n">recv_data</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sock</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sock</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">sal_tls_test</span><span class="p">,</span> <span class="n">SAL</span> <span class="n">TLS</span> <span class="n">function</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="bsd-socket-api">BSD Socket API +</h2><h4 id="1创建套接字socket">1.创建套接字(socket) +</h4><p>为通信创建一个端点并返回一个文件描述符</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">socket</span><span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>domain:确定协议簇</li> +<li>type:数据类型</li> +<li>protocol:协议</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># domain / 协议族类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">AF_INET</span> <span class="err">#</span> <span class="n">IPv4</span> <span class="err">协议族</span> +</span></span><span class="line"><span class="cl"><span class="n">AF_INET6</span> <span class="err">#</span> <span class="n">IPv6</span> <span class="err">协议族</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp"># type / 协议类型 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/* Socket protocol types (1:TCP/2:UDP/3:RAW) */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_STREAM 1 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_DGRAM 2 +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SOCK_RAW 3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2绑定套接字bind">2.绑定套接字(bind) +</h4><p>当使用socket()创造一个套接字时,只是给定了协议簇,并没有分配地址。在套接字能够接收来自其他主机的连接时,必须bind()给它绑定一个地址。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bind</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:代表socket的文件描述符</li> +<li>name:指向sockaddr结构体的指针,代表要绑定的地址</li> +<li>namelen:是sockaddr结构体的大小</li> +</ul> +<p>附:SAL组件依赖netdev组件,当使用bind()函数时,可通过netdev网卡名称获取网卡对象中IP地址信息,用于将创建的Socket套接字绑定到指定的网卡对象。</p> +<p>来自RT-Thread文档中心,完成通过传入的网卡名称绑定该网卡IP地址并和服务器进行连接的过程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;arpa/inet.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;netdev.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_HOST &#34;192.168.1.123&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#define SERVER_PORT 1234 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">bing_test</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">netdev</span> <span class="o">*</span><span class="n">netdev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sockfd</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;bind_test [netdev_name] --bind network interface device by name.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 通过名称获取 netdev 网卡对象 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">netdev</span> <span class="o">=</span> <span class="nf">netdev_get_by_name</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">netdev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;get network interface device(%s) failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">sockfd</span> <span class="o">=</span> <span class="nf">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Socket create failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化需要绑定的客户端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 获取网卡对象中 IP 地址信息 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">ip_addr</span><span class="p">.</span><span class="n">addr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">bind</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind failed.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket bind network interface device(%s) success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">netdev</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 初始化预连接的服务端地址 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="nf">htons</span><span class="p">(</span><span class="n">SERVER_PORT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="nf">inet_addr</span><span class="p">(</span><span class="n">SERVER_HOST</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="o">&amp;</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">.</span><span class="n">sin_zero</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 连接到服务端 */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">connect</span><span class="p">(</span><span class="n">sockfd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;socket connect success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 关闭连接 */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">closesocket</span><span class="p">(</span><span class="n">sockfd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FINSH_USING_MSH +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;finsh.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">bing_test</span><span class="p">,</span> <span class="n">bind</span> <span class="n">network</span> <span class="n">interface</span> <span class="n">device</span> <span class="n">test</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FINSH_USING_MSH */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3监听套接字listen">3.监听套接字(listen) +</h4><p>当有一个套接字和一个地址联系之后,listen()监听到来的连接。只适用于面向连接的模式。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">listen</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>sockfd:代表socket的文件描述符</li> +<li>backlog:一个整数,表示一次能够等待的最大连接数目。</li> +</ul> +<h4 id="4接收连接accept">4.接收连接(accept) +</h4><p>当应用程序监听来自其他他主机的面向数据流的连接时,通过事件通知它,必须用accept()函数初始化连接。该函数为每个连接创建新的套接字并从监听队列中移除这个连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">accept</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:监听的套接字描述符</li> +<li>addr:指向sockaddr结构体的指针,服务器地址信息</li> +<li>addrlen:sockaddr结构体的大小</li> +</ul> +<h4 id="5建立连接connect">5.建立连接(connect) +</h4><p>该函数用于建立与指定 socket 的连接。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">connect</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>name:服务器地址信息</li> +<li>namelen:服务器地址结构体长度</li> +</ul> +<h4 id="6tcp数据发送send">6.TCP数据发送(send) +</h4><p>该函数常用于 TCP 连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">send</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为 0</li> +</ul> +<h4 id="7tcp数据接收recv">7.TCP数据接收(recv) +</h4><p>该函数用于TCP连接接收数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recv</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>s:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +</ul> +<h4 id="8udp数据发送sendto">8.UDP数据发送(sendto) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sendto</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dataptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>dataptr:发送的数据指针</li> +<li>size:发送的数据长度</li> +<li>flags:标志,一般为0</li> +<li>to:目标结构体指针</li> +<li>tolen:目标地址结构体长度</li> +</ul> +<h4 id="9udp数据接收recfrom">9.UDP数据接收(recfrom) +</h4><p>该函数用于UDP连接发送数据。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">recvfrom</span><span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>S:套接字描述符</li> +<li>mem:接收的数据指针</li> +<li>len:接收的数据长度</li> +<li>flags:标志,一般为0</li> +<li>from:接收地址结构体指针</li> +<li>fromlen:接收地址结构体长度</li> +</ul> +<h2 id="sal网络协议栈接入方式">SAL网络协议栈接入方式 +</h2><p>网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到SAL组件中协议簇列表中,协议簇结构体定义如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* network interface socket opreations */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_socket_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">socket</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">domain</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="kt">int</span> <span class="n">protocol</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">closesocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">bind</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">listen</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">backlog</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">connect</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">accept</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">addrlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">sendto</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">to</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">tolen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">recvfrom</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">mem</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">from</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">fromlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">setsockopt</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">level</span><span class="p">,</span> <span class="kt">int</span> <span class="n">optname</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">optval</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="n">optlen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">shutdown</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">how</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getpeername</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getsockname</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">socklen_t</span> <span class="o">*</span><span class="n">namelen</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ioctlsocket</span><span class="p">)(</span><span class="kt">int</span> <span class="n">s</span><span class="p">,</span> <span class="kt">long</span> <span class="n">cmd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef SAL_USING_POSIX +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">poll</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">dfs_fd</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">struct</span> <span class="n">rt_pollreq</span> <span class="o">*</span><span class="n">req</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* sal network database name resolving */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_netdb_ops</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">hostent</span><span class="o">*</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">gethostbyname_r</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">*</span><span class="n">ret</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">buflen</span><span class="p">,</span> <span class="k">struct</span> <span class="n">hostent</span> <span class="o">**</span><span class="n">result</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h_errnop</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">getaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">nodename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">servname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">hints</span><span class="p">,</span> <span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">**</span><span class="n">res</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">freeaddrinfo</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">addrinfo</span> <span class="o">*</span><span class="n">ai</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* 协议簇结构体定义 */</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">sal_proto_family</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">family</span><span class="p">;</span> <span class="cm">/* primary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sec_family</span><span class="p">;</span> <span class="cm">/* secondary protocol families type */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_socket_ops</span> <span class="o">*</span><span class="n">skt_ops</span><span class="p">;</span> <span class="cm">/* socket opreations */</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">sal_netdb_ops</span> <span class="o">*</span><span class="n">netdb_ops</span><span class="p">;</span> <span class="cm">/* network database opreations */</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>family:每个协议栈支持的主协议簇类型,例如lwip的为AF_INET、AT Socket为AF_AT,WIZnet为AF_WIZ。</li> +<li>sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。</li> +<li>skt_ops:定义socket相关执行函数,如connect、send、recv等,每种协议簇都有一组通过的实现方式。</li> +<li>netdb_ops:定义非socket相关执行函数,如gethostbyname、getaddrinfo、freeaddrinfo等,每种协议簇都有一组不同的实现方式。</li> +</ul> +<hr> +<h2 id="附录">附录 +</h2><div class="footnotes" role="doc-endnotes"> +<hr> +<ol> +<li id="fn:1"> +<p>伯克利套接字(Berkeley sockets),也称BSD Socket,伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的<strong>抽象标准</strong>。大多数其他程序语言使用一种相似的编程接口。最初是由加州伯克利大学为Unix系统开发出来。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:2"> +<p>WIZnet的硬件TCP/IP协议栈采用了TOE(TCP/IP Core Offload Engine)技术,将T<strong>CP/IP协议栈等网络处理功能转移到专用硬件中,从而减少了CPU的负担</strong>,提高了整个系统的性能和稳定性。同时,WIZnet的硬件TCP/IP协议栈还支持多种网络协议,并提供了Socket API封装等高层次接口,方便用户进行开发和集成。&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +<li id="fn:3"> +<p>在 TLS 协议中,使用了非对称加密和对称加密两种加密方式。其中,<strong>非对称加密主要用于密钥协商和身份认证,而对称加密则用于数据传输的加密和解密</strong>。在TLS握手过程中,客户端和服务器会相互发送自己的公钥,并通过对方的公钥加密生成一个随机数的方式协商出用来进行对称加密的对称密钥。这个对称密钥就是用非对称加密算法加密后的数据包。接收方拿到这个数据包后,使用自己的私钥进行解密,获取生成的对称密钥。然后,双方就开始使用协商好的对称密钥进行数据传输。接收方会利用对称密钥对收到的数据进行解密,得到明文数据。这样,在整个数据传输过程中,只有公钥被公开,密钥等关键信息都是使用非对称加密算法进行加密传输的,保证了安全性。总之,在 TLS 协议中,接收方通过使用自己的私钥解密协商出的对称密钥,从而完成对加密数据的解析。这个过程是整个 TLS 协议中非常重要的一个环节,确保了加密数据在传输过程中的安全性和可靠性。&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> +</li> +</ol> +</div> \ No newline at end of file diff --git "a/tags/sal\345\245\227\346\216\245\345\255\227/page/1/index.html" "b/tags/sal\345\245\227\346\216\245\345\255\227/page/1/index.html" new file mode 100644 index 000000000..3920650df --- /dev/null +++ "b/tags/sal\345\245\227\346\216\245\345\255\227/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/sal%E5%A5%97%E6%8E%A5%E5%AD%97/ + \ No newline at end of file diff --git a/tags/scripy/index.html b/tags/scripy/index.html new file mode 100644 index 000000000..b044145de --- /dev/null +++ b/tags/scripy/index.html @@ -0,0 +1,55 @@ +Tag: Scripy - kurisaW +

Tags

2 pages

Scripy

\ No newline at end of file diff --git a/tags/scripy/index.xml b/tags/scripy/index.xml new file mode 100644 index 000000000..96faa8258 --- /dev/null +++ b/tags/scripy/index.xml @@ -0,0 +1,242 @@ +Scripy on kurisaWhttps://kurisaw.github.io/tags/scripy/Recent content in Scripy on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Git版本控制】在Linux终端显示Git版本信息https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E5%9C%A8linux%E7%BB%88%E7%AB%AF%E6%98%BE%E7%A4%BAgit%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/cover.jpg" alt="Featured image of post 【Git版本控制】在Linux终端显示Git版本信息" /><h2 id="前言">前言 +</h2><p>在使用Git管理项目时,经常需要知道当前所在的分支是哪一个。这个信息对于协作和版本控制非常重要。然而,Git默认情况下并不会在命令行中显示当前分支名称,这可能会导致一些混淆和不便。在本篇博文中,我们将介绍如何通过编辑<code>.bashrc</code>文件,使Git在命令行中显示当前分支的名称,让你的Git工作更加顺畅和高效。</p> +<h3 id="步骤一进入home目录">步骤一:进入home目录 +</h3><p>首先,打开你的终端,并进入home目录。你可以使用以下命令来完成这一步:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">cd</span> ~ +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤二编辑bashrc文件">步骤二:编辑.bashrc文件 +</h3><p>接下来,我们需要编辑<code>.bashrc</code>文件,这是Linux和macOS系统中存储Shell配置的文件。你可以使用vi编辑器或其他文本编辑器来打开它,这里我们以vi为例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vi .bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤三添加代码到文件末尾">步骤三:添加代码到文件末尾 +</h3><p>在打开的<code>.bashrc</code>文件中,将以下代码添加到文件的末尾:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">function</span> git_branch <span class="o">{</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;`git branch 2&gt;/dev/null | grep &#34;</span>^<span class="se">\*</span><span class="s2">&#34; | sed -e &#34;</span>s/^<span class="se">\*\ </span>//<span class="s2">&#34;`&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;(no branch)&#34;</span> <span class="o">]</span><span class="p">;</span><span class="k">then</span> +</span></span><span class="line"><span class="cl"> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;(`git rev-parse --short HEAD`...)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34; (</span><span class="nv">$branch</span><span class="s2">)&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="k">fi</span> +</span></span><span class="line"><span class="cl"><span class="o">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PS1</span><span class="o">=</span><span class="s1">&#39;\u@\h \[\033[01;36m\]\W\[\033[01;32m\]$(git_branch)\[\033[00m\] \$ &#39;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这段代码定义了一个名为<code>git_branch</code>的函数,用于获取并显示当前Git分支的名称。然后,通过<code>export</code>命令将这个信息添加到Shell的提示符中,以便在命令行中实时显示当前分支名称。</p> +<h3 id="步骤四保存并退出vi编辑器">步骤四:保存并退出vi编辑器 +</h3><p>完成以上代码的添加后,按下Esc键退出编辑模式,然后输入以下命令保存并退出vi编辑器:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">:wq +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="步骤五执行命令使配置生效">步骤五:执行命令使配置生效 +</h3><p>最后,执行以下命令来使新的配置生效:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">source</span> ./.bashrc +</span></span></code></pre></td></tr></table> +</div> +</div><p>现在,当你进入一个包含Git仓库的目录时,命令行提示符将会显示当前分支的名称,让你随时了解项目的状态。</p> +<p>通过这个简单的配置,你可以提高Git工作的效率,更轻松地进行版本控制和协作。希望这个小技巧对你的开发工作有所帮助!</p>【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/Wed, 31 May 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%9B%BE%E5%BA%8A%E6%9C%8D%E5%8A%A1action---%E8%87%AA%E5%8A%A8%E7%9B%91%E8%A7%86%E5%9B%BE%E5%BA%8A%E4%BB%93%E5%BA%93%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0/cover.jpg" alt="Featured image of post 【Git版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数" /><h2 id="前言">前言 +</h2><p>最近突然想起年前图床仓库发生的一个遗留问题:由于我的网络图床服务是<code>Github + Typora</code>的形式,本地的图片会自动转义成网络图片并存储在图床仓库下,一般我们会指定一个目录进行图片存储,但是由于GitHub设定的单个目录最大存储文件数不能超过1000.</p> +<p>所以在注意到这件事的情况下GitHub的图床仓库就发生了问题:新加入的图片文件由于没有文件位,会自动代替旧的图片文件,这就导致了部分文件的丢失,所以这里想写一个GitHub仓库的自动化Action,每天检测仓库下每个目录下的文件个数,超过999个文件自动给GitHub默认绑定的邮箱发送信息提醒。</p> +<h2 id="具体流程">具体流程 +</h2><p>当每天自动检测仓库中每个目录中的文件数量,并且如果超过999个文件时,自动向与GitHub账户关联的默认邮箱发送消息。</p> +<h3 id="1-创建github工作流文件">1. 创建GitHub工作流文件 +</h3><p>在GitHub仓库中,转到<code>.github/workflows</code>目录并创建一个新文件,比如<code>file_count.yml</code>。该文件将定义运行自动化操作的工作流。</p> +<h3 id="2-定义工作流">2. 定义工作流 +</h3><p>在<code>file_count.yml</code>文件中,添加以下代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">File Count Reminder</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 0 * * *&#34;</span><span class="w"> </span><span class="c"># Runs every day at midnight UTC</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">count-files</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check out code</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v2</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.10&#39;</span><span class="w"> </span><span class="c"># Replace with the desired Python version</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Count files and send email</span><span class="w"> +</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> +</span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt +</span></span></span><span class="line"><span class="cl"><span class="sd"> python send_email.py ${{ secrets.GITHUB_TOKEN }}</span><span class="w"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><h3 id="3-创建requirementstxt文件">3. 创建<code>requirements.txt</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>requirements.txt</code>的文件,并将以下内容添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">smtplib +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="4-创建send_emailpy文件">4. 创建<code>send_email.py</code>文件 +</h3><p>在GitHub仓库中创建一个名为<code>send_email.py</code>的文件,并将以下代码添加到文件中:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> +</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">smtplib</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> +</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">email.header</span> <span class="kn">import</span> <span class="n">Header</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">count_files</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">file_count</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">files</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">file_count</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">file_count</span><span class="p">):</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_server</span> <span class="o">=</span> <span class="s1">&#39;smtp.gmail.com&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">smtp_port</span> <span class="o">=</span> <span class="mi">587</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">subject</span> <span class="o">=</span> <span class="s1">&#39;File Count Reminder&#39;</span> +</span></span><span class="line"><span class="cl"> <span class="n">content</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;The repository has </span><span class="si">{</span><span class="n">file_count</span><span class="si">}</span><span class="s1"> files.&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">message</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;From&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="s1">&#39;GitHub Action&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;To&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">message</span><span class="p">[</span><span class="s1">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">smtp_server</span><span class="p">,</span> <span class="n">smtp_port</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">starttls</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">github_token</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s1">&#39;githubaction@gmail.com&#39;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">message</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> +</span></span><span class="line"><span class="cl"> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Email reminder sent to&#34;</span><span class="p">,</span> <span class="n">recipient</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Failed to send email:&#34;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">repository_path</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span> <span class="c1"># Replace with the path to your repository if needed</span> +</span></span><span class="line"><span class="cl"><span class="n">file_limit</span> <span class="o">=</span> <span class="mi">999</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">file_count</span> <span class="o">=</span> <span class="n">count_files</span><span class="p">(</span><span class="n">repository_path</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">file_count</span> <span class="o">&gt;</span> <span class="n">file_limit</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">github_token</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;INPUT_GITHUB_TOKEN&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">default_email</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;GITHUB_ACTOR&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;@users.noreply.github.com&#39;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">send_email</span><span class="p">(</span><span class="n">github_token</span><span class="p">,</span> <span class="n">default_email</span><span class="p">,</span> <span class="n">file_count</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The repository has&#34;</span><span class="p">,</span> <span class="n">file_count</span><span class="p">,</span> <span class="s2">&#34;files. No reminder needed.&#34;</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>使用这些步骤,工作流将每天UTC时间午夜运行,计算仓库中的文件数量,如果文件数量超过999,则会向与GitHub账户关联的默认邮箱发送邮件提醒。</p> \ No newline at end of file diff --git a/tags/scripy/page/1/index.html b/tags/scripy/page/1/index.html new file mode 100644 index 000000000..a8f0c9994 --- /dev/null +++ b/tags/scripy/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/scripy/ + \ No newline at end of file diff --git a/tags/sftp/index.html b/tags/sftp/index.html new file mode 100644 index 000000000..b9d4eb8fc --- /dev/null +++ b/tags/sftp/index.html @@ -0,0 +1,55 @@ +Tag: SFTP - kurisaW +

Tags

1 page

SFTP

\ No newline at end of file diff --git a/tags/sftp/index.xml b/tags/sftp/index.xml new file mode 100644 index 000000000..0c1e2b9ec --- /dev/null +++ b/tags/sftp/index.xml @@ -0,0 +1,156 @@ +SFTP on kurisaWhttps://kurisaw.github.io/tags/sftp/Recent content in SFTP on kurisaWHugo -- gohugo.ioenFri, 07 Apr 2023 00:00:00 +0000【Linux系统开发】Ubuntu配置SFTP服务https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/Fri, 07 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91ubuntu%E9%85%8D%E7%BD%AEsftp%E6%9C%8D%E5%8A%A1/cover.jpg" alt="Featured image of post 【Linux系统开发】Ubuntu配置SFTP服务" /><h2 id="sftp介绍">SFTP介绍 +</h2><p>SFTP是指Secure File Transfer Protocol,即安全文件传输协议。它提供了一种安全的网络加密方法来传输文件。SFTP与FTP具有几乎相同的语法和功能,是SSH的其中一部分,可安全地将文件传输到服务器。在SSH软件包中,已经包含了一个名为SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统。SFTP本身没有单独的守护进程,必须使用sshd守护进程(默认端口号为22)来完成相应的连接和答复操作。因此,从某种意义上说,SFTP并不像服务器程序,而更像客户端程序。由于SFTP也使用加密传输认证信息和数据,因此使用SFTP非常安全。但是,由于这种传输方式使用了加密/解密技术,因此传输效率比普通的FTP要低得多。如果您对网络安全性要求更高,可以使用SFTP代替FTP。(参考资料:百度百科)</p> +<h2 id="安装步骤">安装步骤 +</h2><h4 id="1目标">1.目标: +</h4><p>在Ubuntu系统上开通SFTP文件服务,允许某些用户上传及下载文件。这些用户只能使用SFTP传输文件,不能使用SSH终端访问服务器,并且SFTP不能访问系统文件。系统管理员则既能使用SFTP传输文件,也能使用SSH远程管理服务器。 +以下是将允许SFTP-users用户组内的用户使用SFTP,但不允许使用SSH Shell,且该组用户不能访问系统文件。在SFTP-users组内创建一个名为“SFTP”的用户。允许SSH-users用户组内的用户使用SFTP以及SSH。系统管理员的账户名为yifang。</p> +<h4 id="2查看ubuntu系统信息">2.查看Ubuntu系统信息 +</h4><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071010234.png" +loading="lazy" +alt="image-20230407101026858" +></p> +<h4 id="3检查是否已安装sftp">3.检查是否已安装SFTP +</h4><p>在Linux系统中,一般RedHat系统默认已经安装了openssh-client和openssh-server,即默认已经集成了SFTP服务,不需要重新安装;而Ubuntu系统默认只安装了openssh-client,要用SFTP的话还需要安装openssh-server。如果系统已安装有openssh-client,则为了防止安装openssh-server时两者版本不兼容,可以先将openssh-client卸载后再安装。如下所示,如果Ubuntu没有安装SFTP,则会显示没有安装:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071011398.png" +loading="lazy" +alt="image-20230407101132327" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">client</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">client</span> +</span></span><span class="line"><span class="cl"><span class="err">安装</span><span class="n">openssh</span><span class="o">-</span><span class="nl">server</span><span class="p">:</span> <span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">openssh</span><span class="o">-</span><span class="n">server</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里由于我已经完成安装了,此处就不做安装演示,具体下载命令如上所示。</p> +<h4 id="4新建用户组sftp-users并新建用户sftp">4.新建用户组SFTP-users,并新建用户SFTP +</h4><p>为了方便管理权限,创建用户组可以用于SFTP访问。然后创建sftp用户:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">adduser</span> <span class="nf">sftp</span> <span class="p">(</span><span class="err">这部分会让你新建用户组信息,建议最好截图保存下</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5给sftp赋权并新建用户组ssh-users">5.给SFTP赋权并新建用户组SSH-users +</h4><p>将SFTP从其他所有用户组中移除并加入SFTP-users组,然后关闭其Shell访问:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">G</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="nb">false</span> <span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>创建SSH用户组,并将管理员添加到该组(请注意usermod命令中的-a参数意味着不从其他用户组中移除)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">addgroup</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">usermod</span> <span class="o">-</span><span class="n">a</span> <span class="o">-</span><span class="n">G</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">bbc2005</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="6创建并设置sftp用户目录">6.创建并设置SFTP用户目录 +</h4><p>为“监狱”根目录和共享目录做准备,“监狱”根目录必须满足以下要求: +所有者为root,其他任何用户都不能拥有写入权限。因此,为了让SFTP用户能够上传文件,还必须在“监狱”根目录下创建一个普通用户能够写入的共享文件目录。为了方便管理员通过SFTP管理上传的文件,把这个共享文件目录配置为由yifang所有,允许SFTP-users读写,这样,管理员和SFTP用户组成员都能读写这个目录。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">mkdir</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chown</span> <span class="nl">yifang</span><span class="p">:</span><span class="n">sftp</span><span class="o">-</span><span class="n">users</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">chmod</span> <span class="mi">770</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span><span class="o">/</span><span class="n">shared</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="7修改ssh配置文件">7.修改SSH配置文件 +</h4><p>在sshd_config文件的最后添加以下内容:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">vi</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssh</span><span class="o">/</span><span class="n">sshd_config</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">AllowGroups</span> <span class="n">ssh</span><span class="o">-</span><span class="n">users</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">Match</span> <span class="n">Group</span> <span class="n">sftp</span><span class="o">-</span><span class="n">users</span> +</span></span><span class="line"><span class="cl"><span class="n">ChrootDirectory</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">sftp_root</span> +</span></span><span class="line"><span class="cl"><span class="n">AllowTcpForwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"><span class="n">X11Forwarding</span> <span class="n">no</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">ForceCommand</span> <span class="n">internal</span><span class="o">-</span><span class="n">sftp</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这些内容的意思是:</p> +<ul> +<li>只允许ssh-users和SFTP-users通过SSH访问系统;</li> +<li>针对SFTP-users用户,增加一些额外的设置: +<ul> +<li>将/home/sftp_root设置为该组用户的系统根目录(因此它们将不能访问该目录之外的其他系统文件);</li> +<li>禁止TCP forwarding和X11 forwarding;强制该组用户只能使用SFTP。</li> +<li>如果需要进一步了解细节,可以使用“man sshd_config”命令。这样设置之后,SSH用户组可以访问SSH,并且不受其他限制;而SFTP用户组仅能使用SFTP进行访问,并被限制在监狱目录中。</li> +</ul> +</li> +</ul> +<h4 id="8sftp客户端验证">8.SFTP客户端验证 +</h4><p>首先将虚拟机重启:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sudo</span> <span class="n">reboot</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在本地Windows系统中,可以通过SFTP客户端来连接Ubuntu系统的SFTP服务,例如使用RaiDrive。</p> +<p>查看ubuntu网络ip地址</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ifconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071038531.png" +loading="lazy" +alt="image-20230407103802472" +>zhe</p> +<p>这里我的IP地址为192.168.136.128。我们接着打开RaiDrive(安装配置可参考<a class="link" href="https://blog.devyi.com/archives/418/" target="_blank" rel="noopener" +>RaiDrive—将网盘映射为磁盘</a>)</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071044734.png" +loading="lazy" +alt="image-20230407104441660" +></p> +<p>此时我们点击连接并连接成功后会自动在我们windows下自动生成一个名为SFTP的网络磁盘,这时候我们就可以在windows下对虚拟机进行文件操作了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202304071046125.png" +loading="lazy" +alt="image-20230407104643007" +></p> \ No newline at end of file diff --git a/tags/sftp/page/1/index.html b/tags/sftp/page/1/index.html new file mode 100644 index 000000000..b0d0ed539 --- /dev/null +++ b/tags/sftp/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/sftp/ + \ No newline at end of file diff --git a/tags/sfud/index.html b/tags/sfud/index.html new file mode 100644 index 000000000..bfdd58c65 --- /dev/null +++ b/tags/sfud/index.html @@ -0,0 +1,55 @@ +Tag: SFUD - kurisaW +

Tags

1 page

SFUD

\ No newline at end of file diff --git a/tags/sfud/index.xml b/tags/sfud/index.xml new file mode 100644 index 000000000..5566d84f6 --- /dev/null +++ b/tags/sfud/index.xml @@ -0,0 +1,1755 @@ +SFUD on kurisaWhttps://kurisaw.github.io/tags/sfud/Recent content in SFUD on kurisaWHugo -- gohugo.ioenSun, 23 Apr 2023 00:00:00 +0000【NXP】LPC55S69_FAL分区管理与easyflash变量管理https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/Sun, 23 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/<img src="https://kurisaw.github.io/p/nxplpc55s69_fal%E5%88%86%E5%8C%BA%E7%AE%A1%E7%90%86%E4%B8%8Eeasyflash%E5%8F%98%E9%87%8F%E7%AE%A1%E7%90%86/cover.jpg" alt="Featured image of post 【NXP】LPC55S69_FAL分区管理与easyflash变量管理" /><h2 id="1fal组件">1.FAL组件 +</h2><h3 id="11什么是fal">1.1什么是FAL +</h3><p>FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:</p> +<ul> +<li>支持静态可配置的分区表,并可关联多个 Flash 设备;</li> +<li>分区表支持 <strong>自动装载</strong> 。避免在多固件项目,分区表被多次定义的问题;</li> +<li>代码精简,对操作系统 <strong>无依赖</strong> ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;</li> +<li>统一的操作接口。保证了文件系统、OTA、NVM(例如:<a class="link" href="https://github.com/armink-rtt-pkgs/EasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;</li> +<li>自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231620423.png" +loading="lazy" +alt="image-20230423162047252" +></p> +<p>通过上图我们也可以清晰明了看到,FAL抽象层向下可以通过Flash硬件进行统一管理,当然也可以使用SFUD框架(串行Flash通用驱动库,这部分RT-Thread官方已完成框架的移植同时提供多个应用历程),而对上也可以使用如DFS、NVM提供的Flash硬件统一访问接口,方便用户更加直接方便对底层flash硬件的访问操作。</p> +<p>注:非易失性存储器 (NVM):在芯片电源关闭期间保存存储在其中的数据。 因此,它被用于没有磁盘的便携式设备中的内存,以及用于可移动存储卡等用途。 主要类型有:非易失性半导体存储器 (Non-volatile semiconductor memory, NVSM) 将数据存储在浮栅存储单元中,每个单元都由一个浮栅(floating-gate) MOSFET 组成。</p> +<p>关于存储,可以用一张图来解释:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231641751.png" +loading="lazy" +alt="image-20230423164134689" +></p> +<blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/lianyunyouyou/article/details/118277207" target="_blank" rel="noopener" +>ROM、RAM、FLASH、NVM……一文搞定</a></p> +</blockquote> +<h3 id="12-使用env配置fal">1.2 使用ENV配置FAL +</h3><p>在RT-Thread v4.1.0之前,FAL是作为软件包形式对用户开放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定义为RTT组件的一部分,这样也能更加方便用户的开发。</p> +<p>我们下面正式讲解FAL组件的使用:</p> +<p>首先打开ENV工具,根据以下路径打开FAL使能<code>RT-Thread Components-&gt;[*]FAL: flash abstraction layer</code>,由于我们后面会用到SFUD,所以这里把<code>FAL uses SFUD drivers</code>一并使能,并修改FAL设备名称为<code>W25Q128</code>.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231647583.png" +loading="lazy" +alt="image-20230423164700491" +></p> +<p>完成上述操作后保存退出,并使用<code>scons --target=mdk5</code>重新生成MDK5文件并打开</p> +<h3 id="13-fal-sfud-移植">1.3 FAL SFUD 移植 +</h3><p>为了提供示例,我们选用<code>W25Q128 spi flash</code>作为测试模块,并且使用SFUD框架对spi flash设备进行管理和驱动。</p> +<p>由于目前RT-Thread的SFUD已经对<code>W25Q128 </code>完成支持,根据官方的使用手册,我们仅需编写<code>fal_cfg.h</code>文件完成对<code>FAL_FLASH_DEV_TABLE</code>及<code>FAL_PART_TABLE</code>的定义即可。文件存放路径:<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h</code></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// fal.cfg.h +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp">#define _FAL_CFG_H_ +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;board.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#ifndef FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME &#34;norflash0&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp">#else +</span></span></span><span class="line"><span class="cl"><span class="cp">#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Flash device Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cm">/* flash device table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_FLASH_DEV_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> &amp;nor_flash0, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* Partition Configuration */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FAL_PART_HAS_TABLE_CFG +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* partition table */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#define FAL_PART_TABLE \ +</span></span></span><span class="line"><span class="cl"><span class="cp">{ \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;easyflash&#34;, NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;download&#34;, NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;wifi_image&#34;, NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;font&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp"> {FAL_PART_MAGIC_WROD, &#34;filesystem&#34;, NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \ +</span></span></span><span class="line"><span class="cl"><span class="cp">} +</span></span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* FAL_PART_HAS_TABLE_CFG */</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* _FAL_CFG_H_ */</span><span class="cp"> +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>此时编译的话是找不到该头文件的,需要我们在Keil中设置:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231748300.png" +loading="lazy" +alt="image-20230423174802203" +></p> +<p>在RTT FAL组件中的SFUD提供的<code>fal_flash_dev</code>对象默认的<code>nor_flash0</code>参数中,flash大小默认为8M,而<code>W25Q128</code>最大最16M,我们可以选择在<code>.\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c</code>文件中对<code>struct fal_flash_dev nor_flash0</code>进行修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="n">nor_flash0</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">FAL_USING_NOR_FLASH_DEV_NAME</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">addr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">blk_size</span> <span class="o">=</span> <span class="mi">4096</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="p">{</span><span class="n">init</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">write</span><span class="p">,</span> <span class="n">erase</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="n">write_gran</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然也可以选择不进行修改,根据大佬的原话就是<strong>因为在调用初始化接口函数init后,会从flash设备读取正确的参数更新到nor_flash0表项中,我们在使用FAL组件前都需要调用FAL初始化函数fal_init,其内调用flash设备初始化函数fal_flash_init,最后会调用注册到fal_flash_dev设备表项中的初始化函数device_table[i]-&gt;ops.init,所以nor_flash0表项参数会在FAL初始化时被更新。</strong></p> +<p>同时我们需要开启SFUD框架支持,打开ENV工具,由于SFUD的使用需要指定一个spi设备,这里我选择使用最近移植好的软件spi,路径<code>Hardware Drivers Config-&gt;On-chip Peripheral Drivers-&gt;[*] Enable soft SPI BUS-&gt; [*] Enable soft SPI1 BUS (software simulation)</code>,这里我的测试开发板是恩智浦的LPC55S69-EVK,并且这款bsp的软件模拟spi由我本人对接,关于这部分的软件spi引脚定义可以选用默认即可,当然也可以使用自定义引脚,记住不要与其他引脚产生冲突。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231712081.png" +loading="lazy" +alt="image-20230423171229953" +></p> +<p>此时我们回到ENV主界面,进入<code>RT-Thread Components-&gt;Device Drivers-&gt;Using Serial Flash Universal Driver</code>,此时我们才可以看到SFUD选项出现(如果没有使能spi是没法看到的),使能后保持默认即可</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231716493.png" +loading="lazy" +alt="image-20230423171646352" +></p> +<p>到这里,ENV的配置暂时告一段落!</p> +<h3 id="14-fal-sfud-测试用例">1.4 FAL SFUD 测试用例 +</h3><p>为了验证<code>W25Q128</code>及软件模拟spi在SFUD框架上是否能够成功运行,我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建一个<code>soft_spi_flash_init.c</code>文件,代码如下</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;rtthread.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;spi_flash_sfud.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_soft_spi.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;drv_pin.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtconfig.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define cs_pin GET_PINS(1,9) +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">rt_soft_spi_flash_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="nf">rt_hw_softspi_device_attach</span><span class="p">(</span><span class="s">&#34;sspi1&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">,</span> <span class="n">cs_pin</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;value is %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">result</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">RT_EOK</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;rt_hw_softspi_device_attach successful!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">RT_NULL</span> <span class="o">==</span> <span class="nf">rt_sfud_flash_probe</span><span class="p">(</span><span class="s">&#34;W25Q128&#34;</span><span class="p">,</span> <span class="s">&#34;sspi10&#34;</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="n">RT_ERROR</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">RT_EOK</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">INIT_COMPONENT_EXPORT</span><span class="p">(</span><span class="n">rt_soft_spi_flash_init</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里我们需要指定一个片选引脚,我暂时使用了<code>sspi2</code>的SCK引脚作为片选,这里注意不要同时打开<code>sspi1</code>和<code>sspi2</code>,后续我会专门上传一个通用GPIO作为片选引脚,到时候就不会产生问题了。然后软件spi设备的挂载使用的是<code>sspi1 bus</code>及<code>sspi10 device</code>,并且挂载flash设备到<code>sspi10</code>。</p> +<p>另外我们在<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\</code>下新建<code>fal_sample.c</code>文件,并编写测试代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">//fal_sample.c +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="15-测试结果">1.5 测试结果 +</h3><p>到这里就可以进行编译下载了,成功后的截图如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231728293.png" +loading="lazy" +alt="image-20230423172831146" +></p> +<h2 id="2dfs文件系统">2.DFS文件系统 +</h2><h3 id="21-什么是dfs">2.1 什么是DFS +</h3><p>DFS 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231733906.png" +loading="lazy" +alt="image-20230423173347702" +></p> +<p>在 RT-Thread DFS 中,文件系统有统一的根目录,使用 <code>/</code> 来表示。而在根目录下的 f1.bin 文件则使用 <code>/f1.bin</code> 来表示,2018 目录下的 <code>f1.bin</code> 目录则使用 <code>/data/2018/f1.bin</code> 来表示。即目录的分割符号是 <code>/</code>,这与 UNIX/Linux 完全相同,与 Windows 则不相同(Windows 操作系统上使用 <code>\</code> 来作为目录的分割符)。</p> +<h3 id="22-dfs架构">2.2 DFS架构 +</h3><p>RT-Thread DFS 组件的主要功能特点有:</p> +<ul> +<li>为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。</li> +<li>支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。</li> +<li>支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。</li> +</ul> +<p>DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231735074.png" +loading="lazy" +alt="image-20230423173515014" +></p> +<h3 id="23-使用env配置dfs">2.3 使用ENV配置DFS +</h3><p>打开ENV,进入路径<code>RT-Thread Components → DFS: device virtual file system</code>,使能<code>[*] DFS: device virtual file system</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231741428.png" +loading="lazy" +alt="image-20230423174113310" +></p> +<p>由于DFS使用的是POSIX接口,而dfs_posix.h已经在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能<code>RT-Thread Components-&gt;[*] Support legacy version for compatibility</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231808158.png" +loading="lazy" +alt="image-20230423180859035" +></p> +<p>由于elmfat文件系统默认最大扇区大小为512,但我们使用的flash模块<code>W25Q128</code>的Flash扇区大小为4096,为了将elmfat文件系统挂载到W25Q128上,这里的<code>Maximum sector size</code>需要和W25Q128扇区大小保持一致,修改为4096,路径:<code>RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231818347.png" +loading="lazy" +alt="image-20230423181825139" +></p> +<p>保存退出后使用<code>scons --target=mdk5</code>生成MDK5工程。</p> +<h3 id="24-dfs挂载到fal分区测试">2.4 DFS挂载到FAL分区测试 +</h3><p>这里增加FAL flash抽象层,我们将elmfat文件系统挂载到W25Q128 flash设备的filesystem分区上,由于FAL管理的filesystem分区不是块设备,需要先使用FAL分区转BLK设备接口函数将filesystem分区转换为块设备,然后再将DFS elmfat文件系统挂载到filesystem块设备上。</p> +<p>我们接着修改<code>fal_sample.c</code>文件,修改后代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="25-测试结果">2.5 测试结果 +</h3><p>测试结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231822040.png" +loading="lazy" +alt="image-20230423182204922" +></p> +<h2 id="3easyflash移植到fal分区">3.Easyflash移植到FAL分区 +</h2><h3 id="31-简述easyflash">3.1 简述EasyFlash +</h3><p>关于EasyFlash的来源我们已经讲过了,此处不再赘述。<a class="link" href="https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Farmink%2FEasyFlash" target="_blank" rel="noopener" +>EasyFlash</a>是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。</p> +<p>EasyFlash不仅能够实现对产品的 <strong>设定参数</strong> 或 <strong>运行日志</strong> 等信息的掉电保存功能,还封装了简洁的 <strong>增加、删除、修改及查询</strong> 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。</p> +<h3 id="32easyflash软件包使用">3.2EasyFlash软件包使用 +</h3><p>打开ENV进入路径:<code>RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.</code>,选择软件包版本为最新版。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231836146.png" +loading="lazy" +alt="image-20230423183612019" +></p> +<p>配置后退出ENV,同时使用<code>pkgs --update</code>下载软件包,然后再使用<code>scons --target=mdk5</code>重新生成MDK5文件</p> +<h3 id="33-移植easyflash">3.3 移植easyflash +</h3><p>下载完easyflash软件包后,我们复制<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c</code>到目录<code>.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c</code>,双击打开该文件,完成以下修改:</p> +<ul> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改 FAL_EF_PART_NAME 为 easyflash +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define FAL_EF_PART_NAME &#34;easyflash&#34; +</span></span></span></code></pre></td></tr></table> +</div> +</div></li> +<li> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 修改环境变量内容为 {&#34;boot_times&#34;, &#34;0&#34;},这里我们先只设置一个开机次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="k">const</span> <span class="n">ef_env</span> <span class="n">default_env_set</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="s">&#34;0&#34;</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div></li> +</ul> +<h3 id="34-编写easyflash测试用例">3.4 编写Easyflash测试用例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt"> 10 +</span><span class="lnt"> 11 +</span><span class="lnt"> 12 +</span><span class="lnt"> 13 +</span><span class="lnt"> 14 +</span><span class="lnt"> 15 +</span><span class="lnt"> 16 +</span><span class="lnt"> 17 +</span><span class="lnt"> 18 +</span><span class="lnt"> 19 +</span><span class="lnt"> 20 +</span><span class="lnt"> 21 +</span><span class="lnt"> 22 +</span><span class="lnt"> 23 +</span><span class="lnt"> 24 +</span><span class="lnt"> 25 +</span><span class="lnt"> 26 +</span><span class="lnt"> 27 +</span><span class="lnt"> 28 +</span><span class="lnt"> 29 +</span><span class="lnt"> 30 +</span><span class="lnt"> 31 +</span><span class="lnt"> 32 +</span><span class="lnt"> 33 +</span><span class="lnt"> 34 +</span><span class="lnt"> 35 +</span><span class="lnt"> 36 +</span><span class="lnt"> 37 +</span><span class="lnt"> 38 +</span><span class="lnt"> 39 +</span><span class="lnt"> 40 +</span><span class="lnt"> 41 +</span><span class="lnt"> 42 +</span><span class="lnt"> 43 +</span><span class="lnt"> 44 +</span><span class="lnt"> 45 +</span><span class="lnt"> 46 +</span><span class="lnt"> 47 +</span><span class="lnt"> 48 +</span><span class="lnt"> 49 +</span><span class="lnt"> 50 +</span><span class="lnt"> 51 +</span><span class="lnt"> 52 +</span><span class="lnt"> 53 +</span><span class="lnt"> 54 +</span><span class="lnt"> 55 +</span><span class="lnt"> 56 +</span><span class="lnt"> 57 +</span><span class="lnt"> 58 +</span><span class="lnt"> 59 +</span><span class="lnt"> 60 +</span><span class="lnt"> 61 +</span><span class="lnt"> 62 +</span><span class="lnt"> 63 +</span><span class="lnt"> 64 +</span><span class="lnt"> 65 +</span><span class="lnt"> 66 +</span><span class="lnt"> 67 +</span><span class="lnt"> 68 +</span><span class="lnt"> 69 +</span><span class="lnt"> 70 +</span><span class="lnt"> 71 +</span><span class="lnt"> 72 +</span><span class="lnt"> 73 +</span><span class="lnt"> 74 +</span><span class="lnt"> 75 +</span><span class="lnt"> 76 +</span><span class="lnt"> 77 +</span><span class="lnt"> 78 +</span><span class="lnt"> 79 +</span><span class="lnt"> 80 +</span><span class="lnt"> 81 +</span><span class="lnt"> 82 +</span><span class="lnt"> 83 +</span><span class="lnt"> 84 +</span><span class="lnt"> 85 +</span><span class="lnt"> 86 +</span><span class="lnt"> 87 +</span><span class="lnt"> 88 +</span><span class="lnt"> 89 +</span><span class="lnt"> 90 +</span><span class="lnt"> 91 +</span><span class="lnt"> 92 +</span><span class="lnt"> 93 +</span><span class="lnt"> 94 +</span><span class="lnt"> 95 +</span><span class="lnt"> 96 +</span><span class="lnt"> 97 +</span><span class="lnt"> 98 +</span><span class="lnt"> 99 +</span><span class="lnt">100 +</span><span class="lnt">101 +</span><span class="lnt">102 +</span><span class="lnt">103 +</span><span class="lnt">104 +</span><span class="lnt">105 +</span><span class="lnt">106 +</span><span class="lnt">107 +</span><span class="lnt">108 +</span><span class="lnt">109 +</span><span class="lnt">110 +</span><span class="lnt">111 +</span><span class="lnt">112 +</span><span class="lnt">113 +</span><span class="lnt">114 +</span><span class="lnt">115 +</span><span class="lnt">116 +</span><span class="lnt">117 +</span><span class="lnt">118 +</span><span class="lnt">119 +</span><span class="lnt">120 +</span><span class="lnt">121 +</span><span class="lnt">122 +</span><span class="lnt">123 +</span><span class="lnt">124 +</span><span class="lnt">125 +</span><span class="lnt">126 +</span><span class="lnt">127 +</span><span class="lnt">128 +</span><span class="lnt">129 +</span><span class="lnt">130 +</span><span class="lnt">131 +</span><span class="lnt">132 +</span><span class="lnt">133 +</span><span class="lnt">134 +</span><span class="lnt">135 +</span><span class="lnt">136 +</span><span class="lnt">137 +</span><span class="lnt">138 +</span><span class="lnt">139 +</span><span class="lnt">140 +</span><span class="lnt">141 +</span><span class="lnt">142 +</span><span class="lnt">143 +</span><span class="lnt">144 +</span><span class="lnt">145 +</span><span class="lnt">146 +</span><span class="lnt">147 +</span><span class="lnt">148 +</span><span class="lnt">149 +</span><span class="lnt">150 +</span><span class="lnt">151 +</span><span class="lnt">152 +</span><span class="lnt">153 +</span><span class="lnt">154 +</span><span class="lnt">155 +</span><span class="lnt">156 +</span><span class="lnt">157 +</span><span class="lnt">158 +</span><span class="lnt">159 +</span><span class="lnt">160 +</span><span class="lnt">161 +</span><span class="lnt">162 +</span><span class="lnt">163 +</span><span class="lnt">164 +</span><span class="lnt">165 +</span><span class="lnt">166 +</span><span class="lnt">167 +</span><span class="lnt">168 +</span><span class="lnt">169 +</span><span class="lnt">170 +</span><span class="lnt">171 +</span><span class="lnt">172 +</span><span class="lnt">173 +</span><span class="lnt">174 +</span><span class="lnt">175 +</span><span class="lnt">176 +</span><span class="lnt">177 +</span><span class="lnt">178 +</span><span class="lnt">179 +</span><span class="lnt">180 +</span><span class="lnt">181 +</span><span class="lnt">182 +</span><span class="lnt">183 +</span><span class="lnt">184 +</span><span class="lnt">185 +</span><span class="lnt">186 +</span><span class="lnt">187 +</span><span class="lnt">188 +</span><span class="lnt">189 +</span><span class="lnt">190 +</span><span class="lnt">191 +</span><span class="lnt">192 +</span><span class="lnt">193 +</span><span class="lnt">194 +</span><span class="lnt">195 +</span><span class="lnt">196 +</span><span class="lnt">197 +</span><span class="lnt">198 +</span><span class="lnt">199 +</span><span class="lnt">200 +</span><span class="lnt">201 +</span><span class="lnt">202 +</span><span class="lnt">203 +</span><span class="lnt">204 +</span><span class="lnt">205 +</span><span class="lnt">206 +</span><span class="lnt">207 +</span><span class="lnt">208 +</span><span class="lnt">209 +</span><span class="lnt">210 +</span><span class="lnt">211 +</span><span class="lnt">212 +</span><span class="lnt">213 +</span><span class="lnt">214 +</span><span class="lnt">215 +</span><span class="lnt">216 +</span><span class="lnt">217 +</span><span class="lnt">218 +</span><span class="lnt">219 +</span><span class="lnt">220 +</span><span class="lnt">221 +</span><span class="lnt">222 +</span><span class="lnt">223 +</span><span class="lnt">224 +</span><span class="lnt">225 +</span><span class="lnt">226 +</span><span class="lnt">227 +</span><span class="lnt">228 +</span><span class="lnt">229 +</span><span class="lnt">230 +</span><span class="lnt">231 +</span><span class="lnt">232 +</span><span class="lnt">233 +</span><span class="lnt">234 +</span><span class="lnt">235 +</span><span class="lnt">236 +</span><span class="lnt">237 +</span><span class="lnt">238 +</span><span class="lnt">239 +</span><span class="lnt">240 +</span><span class="lnt">241 +</span><span class="lnt">242 +</span><span class="lnt">243 +</span><span class="lnt">244 +</span><span class="lnt">245 +</span><span class="lnt">246 +</span><span class="lnt">247 +</span><span class="lnt">248 +</span><span class="lnt">249 +</span><span class="lnt">250 +</span><span class="lnt">251 +</span><span class="lnt">252 +</span><span class="lnt">253 +</span><span class="lnt">254 +</span><span class="lnt">255 +</span><span class="lnt">256 +</span><span class="lnt">257 +</span><span class="lnt">258 +</span><span class="lnt">259 +</span><span class="lnt">260 +</span><span class="lnt">261 +</span><span class="lnt">262 +</span><span class="lnt">263 +</span><span class="lnt">264 +</span><span class="lnt">265 +</span><span class="lnt">266 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 2006-2023, RT-Thread Development Team +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * SPDX-License-Identifier: Apache-2.0 +</span></span></span><span class="line"><span class="cl"><span class="cm"> * +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Change Logs: +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Date Author Notes +</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2023-04-21 Wangyuqiang the first version +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtthread.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;rtdevice.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;board.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;fal.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dfs_posix.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;easyflash.h&#34;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define FS_PARTITION_NAME &#34;filesystem&#34; +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#define BUF_SIZE 1024 +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">fal_test</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint8_t</span> <span class="n">buf</span><span class="p">[</span><span class="n">BUF_SIZE</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_flash_dev</span> <span class="o">*</span><span class="n">flash_dev</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="k">struct</span> <span class="n">fal_partition</span> <span class="o">*</span><span class="n">partition</span> <span class="o">=</span> <span class="n">RT_NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">partiton_name</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Input param partition name is null!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span> <span class="o">=</span> <span class="nf">fal_partition_find</span><span class="p">(</span><span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">partition</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find partition (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span> <span class="o">=</span> <span class="nf">fal_flash_device_find</span><span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">flash_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Find flash device (%s) failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Flash device : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Flash size : %dK </span><span class="se">\n</span><span class="s">&#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition : %s &#34;</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;Partition size: %dK</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">flash_name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">flash_dev</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* erase all partition */</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_erase_all</span><span class="p">(</span><span class="n">partition</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) erase failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Erase (%s) partition finish!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xFF</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The erase operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* write 0x00 to the specified partition */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_write</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) write failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write (%s) partition finish! Write size %d(%dK).</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partiton_name</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="mi">1024</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* read the specified partition and check data */</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">;)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="n">BUF_SIZE</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">BUF_SIZE</span> <span class="o">?</span> <span class="nl">BUF_SIZE</span> <span class="p">:</span> <span class="p">(</span><span class="n">partition</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">i</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="nf">fal_partition_read</span><span class="p">(</span><span class="n">partition</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Partition (%s) read failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">partition</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x00</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The write operation did not really succeed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* 1- init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;font&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;font&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">fal_test</span><span class="p">(</span><span class="s">&#34;download&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test success!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Fal partition (%s) test failed!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="s">&#34;download&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">fal_sample</span><span class="p">,</span> <span class="n">fal</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fal_elmfat_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">statfs</span> <span class="n">elm_stat</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="n">blk_dev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;elmfat mount to W25Q flash.&#34;</span><span class="p">,</span> <span class="n">buf</span><span class="p">[</span><span class="mi">80</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* create block device */</span> +</span></span><span class="line"><span class="cl"> <span class="n">blk_dev</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fal_blk_device</span> <span class="o">*</span><span class="p">)</span><span class="nf">fal_blk_device_create</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">blk_dev</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Can&#39;t create a block device on &#39;%s&#39; partition.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Create a block device on the %s partition of flash successful.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* make a elmfat format filesystem */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mkfs</span><span class="p">(</span><span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="n">FS_PARTITION_NAME</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make elmfat filesystem success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* mount elmfat file system to FS_PARTITION_NAME */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">dfs_mount</span><span class="p">(</span><span class="n">FS_PARTITION_NAME</span><span class="p">,</span> <span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="s">&#34;elm&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem mount success.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Get elmfat file system statistics */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">statfs</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">elm_stat</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bsize</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_blocks</span><span class="p">,</span> <span class="n">elm_stat</span><span class="p">.</span><span class="n">f_bfree</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">mkdir</span><span class="p">(</span><span class="s">&#34;/user&#34;</span><span class="p">,</span> <span class="mh">0x777</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;make a directory: &#39;/user&#39;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write string &#39;%s&#39; to /user/test.txt.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open the file in create and read-write mode, create the file if it does not exist*/</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Write data done.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* Open file in read-only mode */</span> +</span></span><span class="line"><span class="cl"> <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="s">&#34;/user/test.txt&#34;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="nf">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;Read data from file test.txt(size: %d): %s </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT_ALIAS</span><span class="p">(</span><span class="n">fal_elmfat_sample</span><span class="p">,</span> <span class="n">fal_elmfat</span><span class="p">,</span><span class="n">fal</span> <span class="n">elmfat</span> <span class="n">sample</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">easyflash_sample</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* fal init */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">fal_init</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* easyflash init */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nf">easyflash_init</span><span class="p">()</span> <span class="o">==</span> <span class="n">EF_NO_ERR</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">uint32_t</span> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">c_old_boot_times</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number from Env */</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span> <span class="o">=</span> <span class="nf">ef_get_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* get the boot count number failed */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">c_old_boot_times</span> <span class="o">==</span> <span class="n">RT_NULL</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="n">c_old_boot_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">=</span> <span class="nf">atol</span><span class="p">(</span><span class="n">c_old_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* boot count +1 */</span> +</span></span><span class="line"><span class="cl"> <span class="n">i_boot_times</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;The system now boot %d times</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">rt_kprintf</span><span class="p">(</span><span class="s">&#34;===============================================</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* interger to string */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">sprintf</span><span class="p">(</span><span class="n">c_new_boot_times</span><span class="p">,</span> <span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">i_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* set and store the boot count number to Env */</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_set_env</span><span class="p">(</span><span class="s">&#34;boot_times&#34;</span><span class="p">,</span> <span class="n">c_new_boot_times</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">ef_save_env</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="nf">MSH_CMD_EXPORT</span><span class="p">(</span><span class="n">easyflash_sample</span><span class="p">,</span> <span class="n">easyflash</span> <span class="n">sample</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="35-测试结果">3.5 测试结果 +</h3><p>打开串口助手,输入命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">msh</span> <span class="o">/&gt;</span><span class="n">easyflash_sample</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>第一次命令调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231856640.png" +loading="lazy" +alt="image-20230423185619472" +></p> +<p>第二次RESET开发板后调用:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304231857243.png" +loading="lazy" +alt="image-20230423185703046" +></p> +<h2 id="4结语">4.结语 +</h2><p>至此本博客就到此结束,经历从移植软件模拟spi框架到LPC55S69,到移植过程中遇到不断的问题,到最后解决所有问题并提供应用示例,完成开发日记、开发笔记及应用教学,这个过程确实使我受益良多,其中感受最深的就是当然也更加感谢的是一些前辈们的指点迷津和博文记录,就目前国内嵌入式这个领域,相关开发经验相比较其他计算机行业确实有些不够包容和开放,也希望未来的朋友们能够怀揣着一颗求知及授学之心,共同建设好这个领域!</p> +<h2 id="5联系">5.联系 +</h2><ul> +<li><a class="link" href="mailto:yifang.wangyq@foxmail.com" >Email :yifang.wangyq@foxmail.com</a></li> +<li><a class="link" href="https://github.com/kurisaW" target="_blank" rel="noopener" +>Github Address :https://github.com/kurisaW</a></li> +<li><a class="link" href="https://kurisaw.github.io/" target="_blank" rel="noopener" +>My Website :https://kurisaw.github.io</a></li> +</ul> \ No newline at end of file diff --git a/tags/sfud/page/1/index.html b/tags/sfud/page/1/index.html new file mode 100644 index 000000000..cf4af81ab --- /dev/null +++ b/tags/sfud/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/sfud/ + \ No newline at end of file diff --git a/tags/ssh/index.html b/tags/ssh/index.html new file mode 100644 index 000000000..3e8e81dfa --- /dev/null +++ b/tags/ssh/index.html @@ -0,0 +1,55 @@ +Tag: Ssh - kurisaW +

Tags

1 page

Ssh

\ No newline at end of file diff --git a/tags/ssh/index.xml b/tags/ssh/index.xml new file mode 100644 index 000000000..aa35d857b --- /dev/null +++ b/tags/ssh/index.xml @@ -0,0 +1,105 @@ +Ssh on kurisaWhttps://kurisaw.github.io/tags/ssh/Recent content in Ssh on kurisaWHugo -- gohugo.ioenSat, 16 Sep 2023 00:00:00 +0000【Git版本控制】Github和Gitlab同时使用sshhttps://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/Sat, 16 Sep 2023 00:00:00 +0000https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/<img src="https://kurisaw.github.io/p/git%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6github%E5%92%8Cgitlab%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8ssh/cover.jpg" alt="Featured image of post 【Git版本控制】Github和Gitlab同时使用ssh" /><h2 id="前言">前言 +</h2><p>最近在使用 WSL 时会同时用到 GitHub和 Gitlab ,因此与传统配置 ssh 方式有些不一样的地方,这里特别记录一下</p> +<h2 id="本地生成公私密钥">本地生成公私密钥 +</h2><p>首先确保把之前的 ssh 信息清除,也可以将整个 <code>~/.ssh</code> 目录删除</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rm -rf ~/.ssh/* +</span></span></code></pre></td></tr></table> +</div> +</div><p>我们分别生成 Github 和 Gitlab账号的 SSH 密钥</p> +<ul> +<li>Github 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C 2053731441@qq.com -f ~/.ssh/github_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab 生成密钥</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh-keygen -t rsa -C wangyuqiang@rt-thread.com -f ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意不要选择其他操作,一路回车即可</p> +<p>此时打开 <code>~/.ssh/</code> 目录可以看到生成了四个文件:<code>github_id-rsa github_id-rsa.pub gitlab_id-rsa gitlab_id-rsa.pub</code></p> +<p>其中 <code>.pub</code> 后缀的文件为公钥,需要上传到远程仓库SSH;没有后缀的则是私钥,本地留存</p> +<h2 id="远程仓库-ssh-填写公钥密钥">远程仓库 SSH 填写公钥密钥 +</h2><p>我们先打开 Github 的 Settings选项,然后选择 <code>SSH and GPG keys-&gt;New SSH key</code> ,<code>Title</code>可以随意拟定,<code>Key</code>需要查看刚刚的 <code>github_id-rsa.pub</code> 文件,并且复制到 Gitlab 的<code>key</code>一栏中;</p> +<p>Gitlab 的操作方式与 Github 类似,具体步骤:</p> +<p>打开 <code>Gitlab -&gt; 用户设置 -&gt; SSH密钥</code> ,在密钥一栏填入 <code>gitlab_id-rsa.pub</code>文件中的具体值,标题自拟即可。</p> +<h2 id="配置不同-host-的-ssh-key">配置不同 Host 的 SSH Key +</h2><p>回到 <code>~/.ssh/</code> 目录下,并且创建一个名为 <code>config</code> 的文件,在该文件中填写以下具体代码,其中部分参数依照自己的信息填写:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#github</span> +</span></span><span class="line"><span class="cl">Host github.com +</span></span><span class="line"><span class="cl"> Hostname ssh.github.com +</span></span><span class="line"><span class="cl"> Port <span class="m">443</span> +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/github_id-rsa +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">#gitlab</span> +</span></span><span class="line"><span class="cl">host git.rt-thread.com +</span></span><span class="line"><span class="cl"> Hostname git.rt-thread.com +</span></span><span class="line"><span class="cl"> User git +</span></span><span class="line"><span class="cl"> IdentityFile ~/.ssh/gitlab_id-rsa +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/figure/ssh-config.png" +loading="lazy" +></p> +<h2 id="验证">验证 +</h2><p>使用下面的命令分别验证 Github 和 Gitlab的 SSH 配置</p> +<ul> +<li>Github SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@github.com +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>Gitlab SSH 验证</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh -T git@rt-thread.com +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果出现如下提示即表示远程仓库 SSH 公钥和本地 SSH 密钥配对成功</p> +<p><img src="https://kurisaw.github.io/figure/valid-ssh.png" +loading="lazy" +></p> \ No newline at end of file diff --git a/tags/ssh/page/1/index.html b/tags/ssh/page/1/index.html new file mode 100644 index 000000000..d22f1e4bc --- /dev/null +++ b/tags/ssh/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ssh/ + \ No newline at end of file diff --git a/tags/tcp/ip/index.html b/tags/tcp/ip/index.html new file mode 100644 index 000000000..5be66e446 --- /dev/null +++ b/tags/tcp/ip/index.html @@ -0,0 +1,55 @@ +Tag: TCP/IP - kurisaW +

Tags

1 page

TCP/IP

\ No newline at end of file diff --git a/tags/tcp/ip/index.xml b/tags/tcp/ip/index.xml new file mode 100644 index 000000000..53033d60d --- /dev/null +++ b/tags/tcp/ip/index.xml @@ -0,0 +1,56 @@ +TCP/IP on kurisaWhttps://kurisaw.github.io/tags/tcp/ip/Recent content in TCP/IP on kurisaWHugo -- gohugo.ioenMon, 10 Apr 2023 00:00:00 +0000【网络编程】OSI七层模型&TCPIP四层模型https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/<img src="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover.jpg" alt="Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型" /><h2 id="osi七层模型">OSI七层模型 +</h2><p>七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。</p> +<h4 id="1物理层">1.物理层 +</h4><p><code>建立、维护、断开物理连接。</code>(由底层网络定义协议)</p> +<p>机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。</p> +<p>应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。</p> +<h4 id="2数据链路层">2.数据链路层 +</h4><p><code>建立逻辑连接、进行硬件地址寻址、差错校验等功能。</code>(由底层网络定义协议)</p> +<p>将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)</p> +<h4 id="3网络层">3.网络层 +</h4><p><code>进行逻辑地址寻址,实现不同网络之间的路径选择。</code></p> +<p>控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)</p> +<h4 id="4传输层">4.传输层 +</h4><p><code>定义传输数据的协议端口号,以及流控和差错校验。</code> +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层</p> +<h4 id="5会话层">5.会话层 +</h4><p><code>建立、管理、终止会话。</code>(在五层模型里面已经合并到了应用层)</p> +<p>不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)</p> +<h4 id="6表示层">6.表示层 +</h4><p><code>数据的表示、安全、压缩。</code>(在五层模型里面已经合并到了应用层)</p> +<p>信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)</p> +<h4 id="7应用层">7.应用层 +</h4><p><code>网络服务与最终用户的一个接口</code></p> +<p>各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)</p> +<hr> +<h2 id="tcpip-四层模型">TCP/IP 四层模型 +</h2><p>TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是<strong>指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇</strong>, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304101020851.png" +loading="lazy" +alt="20201028134158932" +></p> +<p>TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示</p> +<h4 id="1应用层">1.应用层 +</h4><p><code>应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。</code></p> +<ul> +<li>应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次</li> +<li>对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议</li> +<li>应用层还能加密、解密、格式化数据</li> +<li>应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源</li> +</ul> +<h4 id="2传输层">2.传输层 +</h4><p><code>作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用</code></p> +<h4 id="3网络层-1">3.网络层 +</h4><p><code>网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能</code></p> +<h4 id="4网络接口层">4.网络接口层 +</h4><p><code>在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路</code></p> \ No newline at end of file diff --git a/tags/tcp/ip/page/1/index.html b/tags/tcp/ip/page/1/index.html new file mode 100644 index 000000000..84006aebe --- /dev/null +++ b/tags/tcp/ip/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/tcp/ip/ + \ No newline at end of file diff --git a/tags/ubuntu/index.html b/tags/ubuntu/index.html new file mode 100644 index 000000000..6d039d910 --- /dev/null +++ b/tags/ubuntu/index.html @@ -0,0 +1,55 @@ +Tag: Ubuntu - kurisaW +

Tags

1 page

Ubuntu

\ No newline at end of file diff --git a/tags/ubuntu/index.xml b/tags/ubuntu/index.xml new file mode 100644 index 000000000..409e18a46 --- /dev/null +++ b/tags/ubuntu/index.xml @@ -0,0 +1,201 @@ +Ubuntu on kurisaWhttps://kurisaw.github.io/tags/ubuntu/Recent content in Ubuntu on kurisaWHugo -- gohugo.ioenMon, 09 Oct 2023 00:00:00 +0000【Linux系统开发】Linux常见开发汇总https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/Mon, 09 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/<img src="https://kurisaw.github.io/p/linux%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91linux%E5%B8%B8%E8%A7%81%E5%BC%80%E5%8F%91%E6%B1%87%E6%80%BB/cover.jpg" alt="Featured image of post 【Linux系统开发】Linux常见开发汇总" /><h2 id="1vmware-tools-灰色无法点击">1.vmware tools 灰色无法点击 +</h2><p>执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get update +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get upgrade +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install open-vm-tools-desktop -y +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2linux安装搜狗输入法">2.linux安装搜狗输入法 +</h2><p>终端安装 fcitx</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install fcitx +</span></span></code></pre></td></tr></table> +</div> +</div><p>到搜狗官方下载 deb 包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://shurufa.sogou.com/linux" target="_blank" rel="noopener" +>https://shurufa.sogou.com/linux</a></li> +</ul> +</blockquote> +<p>使用linux自带的安装程序安装输入法后,安装如下输入法依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2 +</span></span><span class="line"><span class="cl">sudo apt install libgsettings-qt1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启即可</p> +<h2 id="3cmake安装指定版本">3.Cmake安装指定版本 +</h2><p>首先去官网下载所需版本的压缩包:</p> +<blockquote> +<ul> +<li><a class="link" href="https://cmake.org/files/" target="_blank" rel="noopener" +>https://cmake.org/files/</a></li> +</ul> +</blockquote> +<p>执行解压命令</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -zxv -f cmake-3.22.6.tar.gz +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装相关依赖:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install g++ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install libssl-dev +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">sudo apt-get install make +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入解压后的cmake文件,执行:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">./bootstrap +</span></span></code></pre></td></tr></table> +</div> +</div><p>编译构建:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">make +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo make install +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4ubuntu中使用-st-link">4.ubuntu中使用 st-link +</h2><p>安装依赖项:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc +</span></span></code></pre></td></tr></table> +</div> +</div><p>依次执行如下步骤:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># download source code</span> +</span></span><span class="line"><span class="cl">git clone https://github.com/stlink-org/stlink +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> stlink +</span></span><span class="line"><span class="cl"><span class="c1"># build</span> +</span></span><span class="line"><span class="cl">cmake . +</span></span><span class="line"><span class="cl">make +</span></span><span class="line"><span class="cl"><span class="c1"># install</span> +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> bin +</span></span><span class="line"><span class="cl">sudo cp st-* /usr/local/bin +</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ../lib +</span></span><span class="line"><span class="cl">sudo cp *.so* /lib32 +</span></span><span class="line"><span class="cl"><span class="c1"># add rules</span> +</span></span><span class="line"><span class="cl">sudo cp stlink/config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/ +</span></span><span class="line"><span class="cl">sudo udevadm control --reload-rules +</span></span><span class="line"><span class="cl">sudo udevadm trigger +</span></span></code></pre></td></tr></table> +</div> +</div><p>尝试烧录代码</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#check if st-link is plugged</span> +</span></span><span class="line"><span class="cl">sudo st-info --probe +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># write hex</span> +</span></span><span class="line"><span class="cl">sudo st-flash --format ihex write myapp.hex +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 一般下载一次,会失败,需要刷入两次;</span> +</span></span><span class="line"><span class="cl"><span class="c1"># write bin</span> +</span></span><span class="line"><span class="cl">sudo st-flash write in.bin 0x8000000 <span class="c1">#stm32f4xx</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># read bin</span> +</span></span><span class="line"><span class="cl">st-flash <span class="nb">read</span> out.bin 0x8000000 0x1000 +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># restart</span> +</span></span><span class="line"><span class="cl"><span class="c1"># 向嵌入式控制器中下载一次,控制器就不运行了,需要重启一下,才能正常工作</span> +</span></span><span class="line"><span class="cl">sudo st-flash reset +</span></span></code></pre></td></tr></table> +</div> +</div><p>具体的GDB调试可以参考这篇文章:</p> +<blockquote> +<ul> +<li><a class="link" href="https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html" target="_blank" rel="noopener" +>https://club.rt-thread.org/ask/article/cf31a215be3ee5e9.html</a></li> +</ul> +</blockquote> \ No newline at end of file diff --git a/tags/ubuntu/page/1/index.html b/tags/ubuntu/page/1/index.html new file mode 100644 index 000000000..bf164c166 --- /dev/null +++ b/tags/ubuntu/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/ubuntu/ + \ No newline at end of file diff --git a/tags/udp/index.html b/tags/udp/index.html new file mode 100644 index 000000000..2a1d0a80a --- /dev/null +++ b/tags/udp/index.html @@ -0,0 +1,55 @@ +Tag: UDP - kurisaW +

Tags

1 page

UDP

\ No newline at end of file diff --git a/tags/udp/index.xml b/tags/udp/index.xml new file mode 100644 index 000000000..4468982d8 --- /dev/null +++ b/tags/udp/index.xml @@ -0,0 +1,56 @@ +UDP on kurisaWhttps://kurisaw.github.io/tags/udp/Recent content in UDP on kurisaWHugo -- gohugo.ioenMon, 10 Apr 2023 00:00:00 +0000【网络编程】OSI七层模型&TCPIP四层模型https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/<img src="https://kurisaw.github.io/p/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8Btcpip%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B/cover.jpg" alt="Featured image of post 【网络编程】OSI七层模型&TCPIP四层模型" /><h2 id="osi七层模型">OSI七层模型 +</h2><p>七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。</p> +<h4 id="1物理层">1.物理层 +</h4><p><code>建立、维护、断开物理连接。</code>(由底层网络定义协议)</p> +<p>机械、电子、定时接口通信信道上的原始比特流传输TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。</p> +<p>应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC一些典型的 TCP/IP 应用有 FTP、Telnet、SMTP、SNTP、REXEC、TFTP、LPD、SNMP、NFS、INETD 等。RFC 使一些基本相同的 TCP/IP 应用程序实现了标准化,从而使得不同厂家开发的应用程序可以互相通信。</p> +<h4 id="2数据链路层">2.数据链路层 +</h4><p><code>建立逻辑连接、进行硬件地址寻址、差错校验等功能。</code>(由底层网络定义协议)</p> +<p>将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。 +物理寻址、同时将原始比特流转变为逻辑传输线路 +地址解析协议:ARP、PARP(反向地址转换协议)</p> +<h4 id="3网络层">3.网络层 +</h4><p><code>进行逻辑地址寻址,实现不同网络之间的路径选择。</code></p> +<p>控制子网的运行,如逻辑编址、分组传输、路由选择 +协议有:ICMP(互联网控制信息协议) IGMP(组管理协议) IP(IPV4 IPV6)(互联网协议) +安全协议、路由协议(vrrp虚拟路由冗余)</p> +<h4 id="4传输层">4.传输层 +</h4><p><code>定义传输数据的协议端口号,以及流控和差错校验。</code> +接受上一层数据,在必要的时候把数据进行切割,并将这些数据交给网络层,并保证这些数据段有效到达对端 +协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层</p> +<h4 id="5会话层">5.会话层 +</h4><p><code>建立、管理、终止会话。</code>(在五层模型里面已经合并到了应用层)</p> +<p>不同机器上的用户之间建立及管理会话 +对应主机进程,指本地主机与远程主机正在进行的会话 +安全协议:SSL(安全套接字层协议)、TLS(安全传输层协议)</p> +<h4 id="6表示层">6.表示层 +</h4><p><code>数据的表示、安全、压缩。</code>(在五层模型里面已经合并到了应用层)</p> +<p>信息的语法语义以及他们的关联,如加密解密、转换翻译、压缩解压 +格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] +如LPP(轻量级表示协议)</p> +<h4 id="7应用层">7.应用层 +</h4><p><code>网络服务与最终用户的一个接口</code></p> +<p>各种应用程序协议: +HTTP(超文本传输协议)、FTP(文本传输协议)、TFTP(简单文件传输协议)、SMTP(简单邮件传输协议)、SNMP(简单网络管理协议)、DNS(域名系统)、TELNET(远程终端协议)、HTTPS(超文本传输安全协议)、POP3(邮局协议版本3 )、DHCP(动态主机配置协议)</p> +<hr> +<h2 id="tcpip-四层模型">TCP/IP 四层模型 +</h2><p>TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是<strong>指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇</strong>, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304101020851.png" +loading="lazy" +alt="20201028134158932" +></p> +<p>TCP/IP协议在一定程度上参考了OSI的体系结构,在TCP/IP中,OSI的七层模型被简化了四个层面。如下图所示</p> +<h4 id="1应用层">1.应用层 +</h4><p><code>应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的。</code></p> +<ul> +<li>应用层、表示层、会话层三个层次提供的服务相差不是很大,所以在TCP/IP协议中,它们被合并为应用层一个层次</li> +<li>对不同种类的应用程序它们会根据自己的需要来使用应用层的不同协议,邮件传输应用使用了SMTP协议、万维网应用使用了HTTP协议、远程登录服务应用使用了有TELNET协议</li> +<li>应用层还能加密、解密、格式化数据</li> +<li>应用层可以建立或解除与其他节点的联系,这样可以充分节省网络资源</li> +</ul> +<h4 id="2传输层">2.传输层 +</h4><p><code>作为TCP/IP协议的第二层,运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用</code></p> +<h4 id="3网络层-1">3.网络层 +</h4><p><code>网络层在TCP/IP协议中的位于第三层。在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能</code></p> +<h4 id="4网络接口层">4.网络接口层 +</h4><p><code>在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路</code></p> \ No newline at end of file diff --git a/tags/udp/page/1/index.html b/tags/udp/page/1/index.html new file mode 100644 index 000000000..6a493ae8e --- /dev/null +++ b/tags/udp/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/udp/ + \ No newline at end of file diff --git a/tags/usb/index.html b/tags/usb/index.html new file mode 100644 index 000000000..555712e6d --- /dev/null +++ b/tags/usb/index.html @@ -0,0 +1,55 @@ +Tag: USB - kurisaW +

Tags

1 page

USB

\ No newline at end of file diff --git a/tags/usb/index.xml b/tags/usb/index.xml new file mode 100644 index 000000000..0d87f2dfa --- /dev/null +++ b/tags/usb/index.xml @@ -0,0 +1,296 @@ +USB on kurisaWhttps://kurisaw.github.io/tags/usb/Recent content in USB on kurisaWHugo -- gohugo.ioenThu, 26 Oct 2023 00:00:00 +0000【经验分享】WSL中使用USB设备https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【经验分享】WSL中使用USB设备" /><h2 id="具体步骤">具体步骤: +</h2><p>首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:</p> +<blockquote> +<p>下载链接:https://github.com/dorssel/usbipd-win/releases</p> +</blockquote> +<p>同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开wsl ubuntu终端使用命令:<code>uname -r</code>得到版本号,同时根据版本号使用管理员模式新建目录</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7.png" +width="587" +height="103" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="569" +data-flex-basis="1367px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases</p> +<p>这里的版本就是你使用命令 <code>uname -r</code> 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下</p> +<p>然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl">$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ <span class="o">&amp;&amp;</span> sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后将内核的一些配置信息复制到当前文件夹下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp /proc/config.gz config.gz +</span></span><span class="line"><span class="cl">$ sudo gunzip config.gz +</span></span><span class="line"><span class="cl">$ sudo mv config .config +</span></span></code></pre></td></tr></table> +</div> +</div><p>接着我们执行menuconfig命令打开图形化菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入如下路径:<code>&gt; Device Drivers &gt; USB support</code></p> +<p>下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Device Drivers -&gt; USB Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB announce new devices +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB Modem <span class="o">(</span>CDC ACM<span class="o">)</span> support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; VHCI HCD +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support -&gt; USB FTDI Single port Serial Driver +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时记得关闭 <code>Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; Debug messages for USB/IP</code>这一选项,否则调试信息会非常影响你的使用体验</p> +<p>另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>内核编译期间发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" +width="1069" +height="344" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="310" +data-flex-basis="745px" +></p> +<p>这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install dwarves +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo make -j8 <span class="o">&amp;&amp;</span> sudo make modules_install -j8 <span class="o">&amp;&amp;</span> sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现又产生了报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac.png" +width="932" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="300" +data-flex-basis="721px" +></p> +<p>查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo vi .config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装内核时发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png.webp" +width="1200" +height="176" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="681" +data-flex-basis="1636px" +></p> +<p>解决方式有两种:</p> +<ul> +<li>1.可以选择在<code>.config</code>中禁用宏<code>CONFIG_X86_X32</code></li> +<li>2.找到合适的binutils版本使其能够编译</li> +</ul> +<p>我选择的是第一种,根据我在网上找到的说法是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>所以我选择禁用宏<code>CONFIG_X86_X32</code>,之后继续执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make modules_install -j8 +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>之后就可以选择编译 USBIP 工具了:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> tools/usb/usbip +</span></span><span class="line"><span class="cl">$ sudo ./autogen.sh +</span></span><span class="line"><span class="cl">$ sudo ./configure +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>复制工具库位置,以便 usbip 工具可以获取到:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装 usb.ids 以便显示 USB 设备的名称:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt-get install hwdata +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启WSL:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ wsl --shutdown +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面进行测试是否成功: +打开powershell:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl list +</span></span></code></pre></td></tr></table> +</div> +</div><p>假设我们需要在wsl使用的 usb 设备为 <code>ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3)</code>,设备id为 <code>0483:374b</code></p> +<p>我们使用命令附加设备到 wsl2 中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;0483:374b&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" +width="1200" +height="408" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="294" +data-flex-basis="705px" +></p> +<p>此时我们打开一个 wsl 终端,使用命令 <code>lsusb</code> 即可看到附加到 wsl 的设备</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96.png" +width="1146" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="369" +data-flex-basis="887px" +></p> +<p>然后我们再次回到 powershell ,执行 <code>usbipd wsl list</code>命令,可以看到此时的 usb 设备已经成功添加到 wsl 了</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" +width="1200" +height="572" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="209" +data-flex-basis="503px" +></p> \ No newline at end of file diff --git a/tags/usb/page/1/index.html b/tags/usb/page/1/index.html new file mode 100644 index 000000000..edba46cbe --- /dev/null +++ b/tags/usb/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/usb/ + \ No newline at end of file diff --git a/tags/wireshark/index.html b/tags/wireshark/index.html new file mode 100644 index 000000000..67961e381 --- /dev/null +++ b/tags/wireshark/index.html @@ -0,0 +1,55 @@ +Tag: Wireshark - kurisaW +

Tags

1 page

Wireshark

\ No newline at end of file diff --git a/tags/wireshark/index.xml b/tags/wireshark/index.xml new file mode 100644 index 000000000..55ff0fd03 --- /dev/null +++ b/tags/wireshark/index.xml @@ -0,0 +1,274 @@ +Wireshark on kurisaWhttps://kurisaw.github.io/tags/wireshark/Recent content in Wireshark on kurisaWHugo -- gohugo.ioenMon, 10 Apr 2023 00:00:00 +0000Wireshark网络抓包教程https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/Mon, 10 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwireshark%E7%BD%91%E7%BB%9C%E6%8A%93%E5%8C%85%E6%95%99%E7%A8%8B/cover.jpg" alt="Featured image of post Wireshark网络抓包教程" /><blockquote> +<p>来源:<a class="link" href="https://blog.csdn.net/HarveyH/article/details/113731485" target="_blank" rel="noopener" +>转自:WireShark 抓包使用教程&ndash;详细</a></p> +</blockquote> +<h2 id="前言">前言 +</h2><p>Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括:</p> +<p>1、Wireshark软件下载和安装以及Wireshark主界面介绍。</p> +<p>2、WireShark简单抓包示例。通过该例子学会怎么抓包以及如何简单查看分析数据包内容。</p> +<p>3、Wireshark过滤器使用。通过过滤器可以筛选出想要分析的内容。包括按照协议过滤、端口和主机名过滤、数据包内容过滤。</p> +<h2 id="wireshark软件安装">Wireshark软件安装 +</h2><p>软件下载路径:<a class="link" href="https://www.wireshark.org/" target="_blank" rel="noopener" +>wireshark官网</a>。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。</p> +<p>如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:<a class="link" href="http://www.win10pcap.org/download/" target="_blank" rel="noopener" +>win10pcap兼容性安装包</a></p> +<h2 id="wireshark-开始抓包示例"><strong>Wireshark 开始抓包示例</strong> +</h2><p>先介绍一个使用wireshark工具抓取ping命令操作的示例,让读者可以先上手操作感受一下抓包的具体过程。</p> +<p>1、打开wireshark 2.6.5,主界面如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102042369.png" +loading="lazy" +alt="image-20230410204240214" +></p> +<p>2、选择菜单栏上Capture -&gt; Option,勾选WLAN网卡(这里需要根据各自电脑网卡使用情况选择,简单的办法可以看使用的IP对应的网卡)。点击Start。启动抓包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043634.png" +loading="lazy" +alt="image-20230410204301558" +></p> +<p>3、wireshark启动后,wireshark处于抓包状态中。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043120.png" +loading="lazy" +alt="image-20230410204330881" +></p> +<p>4、执行需要抓包的操作,如ping <a class="link" href="https://www.baidu.com" target="_blank" rel="noopener" +>www.baidu.com</a>。</p> +<p>5、操作完成后相关数据包就抓取到了。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 119.75.217.26 and icmp 表示只显示ICPM协议且源主机IP或者目的主机IP为119.75.217.26的数据包。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102043973.png" +loading="lazy" +alt="image-20230410204349768" +></p> +<p>5、wireshark抓包完成,就这么简单。关于wireshark过滤条件和如何查看数据包中的详细内容在后面介绍。</p> +<h2 id="wireshakr抓包界面">Wireshakr抓包界面 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044121.png" +loading="lazy" +alt="image-20230410204417023" +></p> +<p>说明:数据包列表区中不同的协议使用了不同的颜色区分。协议颜色标识定位在菜单栏View --&gt; Coloring Rules。如下所示</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102044221.png" +loading="lazy" +alt="image-20230410204435065" +></p> +<p><strong>WireShark 主要分为这几个界面</strong></p> +<p>1. Display Filter(显示过滤器), 用于设置过滤条件进行数据包列表过滤。菜单路径:Analyze --&gt; Display Filters。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045496.png" +loading="lazy" +alt="image-20230410204500320" +></p> +<p>2. Packet List Pane(数据包列表), 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。 不同协议的数据包使用了不同的颜色区分显示。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045343.png" +loading="lazy" +alt="image-20230410204525166" +></p> +<p>3. Packet Details Pane(数据包详细信息), 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容。数据包详细信息面板是最重要的,用来查看协议中的每一个字段。各行信息分别为</p> +<p>(1)Frame: 物理层的数据帧概况</p> +<p>(2)Ethernet II: 数据链路层以太网帧头部信息</p> +<p>(3)Internet Protocol Version 4: 互联网层IP包头部信息</p> +<p>(4)Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP</p> +<p>(5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045382.png" +loading="lazy" +alt="image-20230410204540297" +></p> +<p><strong>TCP包的具体内容</strong></p> +<p>从下图可以看到wireshark捕获到的TCP包中的每个字段。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102045329.png" +loading="lazy" +alt="image-20230410204557194" +></p> +<p>4. Dissector Pane(数据包字节区)。</p> +<h2 id="wireshark过滤器设置">Wireshark过滤器设置 +</h2><p>初学者使用wireshark时,将会得到大量的冗余数据包列表,以至于很难找到自己自己抓取的数据包部分。wireshar工具中自带了两种类型的过滤器,学会使用这两种过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。</p> +<p>(1)抓包过滤器</p> +<p>捕获过滤器的菜单栏路径为Capture --&gt; Capture Filters。用于<strong>在抓取数据包前设置。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046204.png" +loading="lazy" +alt="image-20230410204620124" +></p> +<p>如何使用?可以在抓取数据包前设置如下。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102046995.png" +loading="lazy" +alt="image-20230410204653927" +></p> +<p>ip host 60.207.246.216 and icmp表示只捕获主机IP为60.207.246.216的ICMP数据包。获取结果如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047470.png" +loading="lazy" +alt="image-20230410204717268" +></p> +<p>(2)显示过滤器</p> +<p>显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。同样上述场景,在捕获时未设置捕获规则直接通过网卡进行抓取所有数据包,如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047185.png" +loading="lazy" +alt="image-20230410204734985" +></p> +<p>执行ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取的数据包列表如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102047584.png" +loading="lazy" +alt="image-20230410204753507" +></p> +<p>观察上述获取的数据包列表,含有大量的无效数据。这时可以通过设置显示器过滤条件进行提取分析信息。ip.addr == 211.162.2.183 and icmp。并进行过滤。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048361.png" +loading="lazy" +alt="image-20230410204815301" +></p> +<p>上述介绍了抓包过滤器和显示过滤器的基本使用方法。**在组网不复杂或者流量不大情况下,使用显示器过滤器进行抓包后处理就可以满足我们使用。**下面介绍一下两者间的语法以及它们的区别。</p> +<p><strong>wireshark过滤器表达式的规则</strong></p> +<p>1、抓包过滤器语法和实例</p> +<p>抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&amp;&amp; 与、|| 或、!非)</p> +<p>(1)协议过滤</p> +<p>比较简单,直接在抓包过滤框中直接输入协议名即可。</p> +<p>TCP,只显示TCP协议的数据包列表</p> +<p>HTTP,只查看HTTP协议的数据包列表</p> +<p>ICMP,只显示ICMP协议的数据包列表</p> +<p>(2)IP过滤</p> +<p>host 192.168.1.104</p> +<p>src host 192.168.1.104</p> +<p>dst host 192.168.1.104</p> +<p>(3)端口过滤</p> +<p>port 80</p> +<p>src port 80</p> +<p>dst port 80</p> +<p>(4)逻辑运算符&amp;&amp; 与、|| 或、!非</p> +<p>src host 192.168.1.104 &amp;&amp; dst port 80 抓取主机地址为192.168.1.80、目的端口为80的数据包</p> +<p>host 192.168.1.104 || host 192.168.1.102 抓取主机为192.168.1.104或者192.168.1.102的数据包</p> +<p>!broadcast 不抓取广播数据包</p> +<p>2、显示过滤器语法和实例</p> +<p>(1)比较操作符</p> +<p>比较操作符有== 等于、!= 不等于、&gt; 大于、&lt; 小于、&gt;= 大于等于、&lt;=小于等于。</p> +<p>(2)协议过滤</p> +<p>比较简单,直接在Filter框中直接输入协议名即可。<strong>注意:协议名称需要输入小写。</strong></p> +<p>tcp,只显示TCP协议的数据包列表</p> +<p>http,只查看HTTP协议的数据包列表</p> +<p>icmp,只显示ICMP协议的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102048252.png" +loading="lazy" +alt="image-20230410204852057" +></p> +<p>(3) ip过滤</p> +<p>ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表</p> +<p>ip.dst==192.168.1.104, 显示目标地址为192.168.1.104的数据包列表</p> +<p>ip.addr == 192.168.1.104 显示源IP地址或目标IP地址为192.168.1.104的数据包列表</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049772.png" +loading="lazy" +alt="image-20230410204937591" +></p> +<p>(4)端口过滤</p> +<p>tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。</p> +<p>tcp.srcport == 80, 只显示TCP协议的源主机端口为80的数据包列表。</p> +<p>tcp.dstport == 80,只显示TCP协议的目的主机端口为80的数据包列表。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102049752.png" +loading="lazy" +alt="image-20230410204953546" +></p> +<p>(5) Http模式过滤</p> +<p>http.request.method==&ldquo;GET&rdquo;, 只显示HTTP GET方法的。</p> +<p>(6)逻辑运算符为 and/or/not</p> +<p>过滤多个条件组合时,使用and/or。比如获取IP地址为192.168.1.104的ICMP数据包表达式为ip.addr == 192.168.1.104 and icmp</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050123.png" +loading="lazy" +alt="image-20230410205019907" +></p> +<p>(7)按照数据包内容过滤。假设我要以IMCP层中的内容进行过滤,可以单击选中界面中的码流,在下方进行选中数据。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050553.png" +loading="lazy" +alt="image-20230410205039366" +></p> +<p>右键单击选中后出现如下界面</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102050685.png" +loading="lazy" +alt="image-20230410205054595" +></p> +<p>选中Select后在过滤器中显示如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051573.png" +loading="lazy" +alt="image-20230410205109402" +></p> +<p>后面条件表达式就需要自己填写。如下我想过滤出data数据包中包含&quot;abcd&quot;内容的数据流。<strong>包含的关键词是contains 后面跟上内容。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051902.png" +loading="lazy" +alt="image-20230410205121718" +></p> +<p>看到这, 基本上对wireshak有了初步了解。</p> +<h2 id="wireshark抓包分析tcp三次握手">Wireshark抓包分析TCP三次握手 +</h2><p>(1)TCP三次握手连接建立过程</p> +<p>Step1:客户端发送一个SYN=1,ACK=0标志的数据包给服务端,请求进行连接,这是第一次握手;</p> +<p>Step2:服务端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给发送端,告诉它,可以通讯了,并且让客户端发送一个确认数据包,这是第二次握手;</p> +<p>Step3:服务端发送一个SYN=0,ACK=1的数据包给客户端端,告诉它连接已被确认,这就是第三次握手。TCP连接建立,开始通讯。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051845.png" +loading="lazy" +alt="image-20230410205135665" +></p> +<p>(2)wireshark抓包获取访问指定服务端数据包</p> +<p>Step1:启动wireshark抓包,打开浏览器输入www.huawei.com。</p> +<p>Step2:使用ping <a class="link" href="https://www.huawei.com" target="_blank" rel="noopener" +>www.huawei.com</a>获取IP。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102051433.png" +loading="lazy" +alt="image-20230410205150253" +></p> +<p>Step3:输入过滤条件获取待分析数据包列表 ip.addr == 211.162.2.183</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052925.png" +loading="lazy" +alt="image-20230410205200760" +></p> +<p>图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。</p> +<p><strong>第一次握手数据包</strong></p> +<p>客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052226.png" +loading="lazy" +alt="image-20230410205215079" +></p> +<p>数据包的关键属性如下:</p> +<p>SYN :标志位,表示请求建立连接</p> +<p>Seq = 0 :初始建立连接值为0,数据包的相对序列号从0开始,表示当前还没有发送数据</p> +<p>Ack =0:初始建立连接值为0,已经收到包的数量,表示当前没有接收到数据</p> +<p><strong>第二次握手的数据包</strong></p> +<p>服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052307.png" +loading="lazy" +alt="image-20230410205230236" +></p> +<p>数据包的关键属性如下:</p> +<p>[SYN + ACK]: 标志位,同意建立连接,并回送SYN+ACK</p> +<p>Seq = 0 :初始建立值为0,表示当前还没有发送数据</p> +<p>Ack = 1:表示当前端成功接收的数据位数,虽然客户端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位。(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)</p> +<p><strong>第三次握手的数据包</strong></p> +<p>客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102052080.png" +loading="lazy" +alt="image-20230410205245006" +></p> +<p>数据包的关键属性如下:</p> +<p>ACK :标志位,表示已经收到记录</p> +<p>Seq = 1 :表示当前已经发送1个数据</p> +<p>Ack = 1 : 表示当前端成功接收的数据位数,虽然服务端没有发送任何有效数据,确认号还是被加1,因为包含SYN或FIN标志位(并不会对有效数据的计数产生影响,因为含有SYN或FIN标志位的包并不携带有效数据)。</p> +<p>就这样通过了TCP三次握手,建立了连接。开始进行数据交互</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053540.png" +loading="lazy" +alt="image-20230410205305433" +></p> +<p>下面针对数据交互过程的数据包进行一些说明:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053537.png" +loading="lazy" +alt="image-20230410205320467" +></p> +<p>数据包的关键属性说明</p> +<p>Seq: 1</p> +<p>Ack: 1: 说明现在共收到1字节数据</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053985.png" +loading="lazy" +alt="image-20230410205335911" +></p> +<p>Seq: 1<br> +Ack: 951: 说明现在服务端共收到951字节数据</p> +<p>在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。如下</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102053340.png" +loading="lazy" +alt="image-20230410205349152" +></p> +<p>其中,对于我们日常的分析有用的就是前面的五个字段。它们的含义是:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。</p> +<h2 id="wireshark分析常用操作">Wireshark分析常用操作 +</h2><p>调整数据包列表中时间戳显示格式。调整方法为View --&gt;Time Display Format --&gt; Date and Time of Day。调整后格式如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img2023/202304102054848.png" +loading="lazy" +alt="image-20230410205401641" +></p> \ No newline at end of file diff --git a/tags/wireshark/page/1/index.html b/tags/wireshark/page/1/index.html new file mode 100644 index 000000000..2ea10cf9c --- /dev/null +++ b/tags/wireshark/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/wireshark/ + \ No newline at end of file diff --git a/tags/wsl/index.html b/tags/wsl/index.html new file mode 100644 index 000000000..f9a3aa7ba --- /dev/null +++ b/tags/wsl/index.html @@ -0,0 +1,55 @@ +Tag: WSL - kurisaW +

Tags

1 page

WSL

\ No newline at end of file diff --git a/tags/wsl/index.xml b/tags/wsl/index.xml new file mode 100644 index 000000000..2f556cae0 --- /dev/null +++ b/tags/wsl/index.xml @@ -0,0 +1,296 @@ +WSL on kurisaWhttps://kurisaw.github.io/tags/wsl/Recent content in WSL on kurisaWHugo -- gohugo.ioenThu, 26 Oct 2023 00:00:00 +0000【经验分享】WSL中使用USB设备https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/Thu, 26 Oct 2023 00:00:00 +0000https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/<img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/cover.jpg" alt="Featured image of post 【经验分享】WSL中使用USB设备" /><h2 id="具体步骤">具体步骤: +</h2><p>首先在windows中安装 USBIP 工具,在GitHub上下载安装包并根据README文档的说明进行操作:</p> +<blockquote> +<p>下载链接:https://github.com/dorssel/usbipd-win/releases</p> +</blockquote> +<p>同时在 WSL Linux 端也需要安装编译内核所需的库和工具,为后续做准备:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool +</span></span></code></pre></td></tr></table> +</div> +</div><p>打开wsl ubuntu终端使用命令:<code>uname -r</code>得到版本号,同时根据版本号使用管理员模式新建目录</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7.png" +width="587" +height="103" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/e6c7f98cdc98394c9085941b369626c7_hu6d5d5753661e9718c36ca0fe088bab7d_13231_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="569" +data-flex-basis="1367px" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo mkdir /usr/src/5.15.90.1-microsoft-standard-WSL2 +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时我们去GitHub下载一份wsl内核源码:https://github.com/microsoft/WSL2-Linux-Kernel/releases</p> +<p>这里的版本就是你使用命令 <code>uname -r</code> 得到的版本号,建议可以先手动安装压缩包,然后使用vscode连接wsl,把文件拖拽到wsl下</p> +<p>然后解压到指定路径下(这部分注意区分版本号,不要一昧照搬命令):</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo tar -xzvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz -C /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> /usr/src/5.15.90.1-microsoft-standard-WSL2/ +</span></span><span class="line"><span class="cl">$ sudo mv WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1/* ./ <span class="o">&amp;&amp;</span> sudo rm -r WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1 +</span></span></code></pre></td></tr></table> +</div> +</div><p>然后将内核的一些配置信息复制到当前文件夹下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp /proc/config.gz config.gz +</span></span><span class="line"><span class="cl">$ sudo gunzip config.gz +</span></span><span class="line"><span class="cl">$ sudo mv config .config +</span></span></code></pre></td></tr></table> +</div> +</div><p>接着我们执行menuconfig命令打开图形化菜单</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make menuconfig +</span></span></code></pre></td></tr></table> +</div> +</div><p>进入如下路径:<code>&gt; Device Drivers &gt; USB support</code></p> +<p>下面是一些必须的添加项,一般默认都是选中的,不过最好还是检查下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Device Drivers -&gt; USB Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB announce new devices +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB Modem <span class="o">(</span>CDC ACM<span class="o">)</span> support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; VHCI HCD +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support +</span></span><span class="line"><span class="cl">Device Drivers -&gt; USB Serial Converter Support -&gt; USB FTDI Single port Serial Driver +</span></span></code></pre></td></tr></table> +</div> +</div><p>同时记得关闭 <code>Device Drivers -&gt; USB Support -&gt; USB/IP -&gt; Debug messages for USB/IP</code>这一选项,否则调试信息会非常影响你的使用体验</p> +<p>另外也可以添加你具体所需的USB模块勾选上,保存退出后执行内核编译</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>内核编译期间发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c.png" +width="1069" +height="344" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22ab297a83f4bfaf40bc2a9546ee238c_hu565d753fb626a3c75cce20fb44cc39bd_29743_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="310" +data-flex-basis="745px" +></p> +<p>这主要是由于系统缺少dwarves软件包导致的,我们使用apt命令安装并继续执行编译:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt install dwarves +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">$ sudo make -j8 <span class="o">&amp;&amp;</span> sudo make modules_install -j8 <span class="o">&amp;&amp;</span> sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>发现又产生了报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac.png" +width="932" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/fe79652443aa3daeb419680393a251ac_hu153a755aa2ef188338b9bb4b2fb8f8c2_27191_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="300" +data-flex-basis="721px" +></p> +<p>查找资料似乎说明的是这仅仅是个警告,我通过禁用BTF的调试信息解决了这个问题</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo vi .config +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 找到宏`CONFIG_DEBUG_INFO_BTF`并将value改为 `n`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装内核时发生报错:</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png.webp" +width="1200" +height="176" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/74dedf7b13810239898885579a948cd1.png_huef029ec2ac474bddd194389cce0e4fc7_35882_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="681" +data-flex-basis="1636px" +></p> +<p>解决方式有两种:</p> +<ul> +<li>1.可以选择在<code>.config</code>中禁用宏<code>CONFIG_X86_X32</code></li> +<li>2.找到合适的binutils版本使其能够编译</li> +</ul> +<p>我选择的是第一种,根据我在网上找到的说法是:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 除非您想要它并且拥有它的用户空间,否则 X32 并不是特别有用。请注意,X32 是 64 位的 x32 ABI,它是编译为在 64 位长模式下运行的“32 位”短指针代码,与真正的本机 32 位二进制/ABI 支持不同。这是一种具有非常具体的利基的特殊模式。</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1"># 您可以在内核配置中禁用[CONFIG_X86_X32](https://cateee.net/lkddb/web-lkddb/X86_X32.html)或获取具有 elf32_x86_64 目标支持的 binutils。如何获取 binutils 取决于您的发行版。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>所以我选择禁用宏<code>CONFIG_X86_X32</code>,之后继续执行命令:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo make modules_install -j8 +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png.webp" +width="1200" +height="643" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/08603c912f855bc06d966116b81a1678.png_hu470e5e8bafee61400d78725d3d6f98b5_118168_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="186" +data-flex-basis="447px" +></p> +<p>之后就可以选择编译 USBIP 工具了:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">cd</span> tools/usb/usbip +</span></span><span class="line"><span class="cl">$ sudo ./autogen.sh +</span></span><span class="line"><span class="cl">$ sudo ./configure +</span></span><span class="line"><span class="cl">$ sudo make install -j8 +</span></span></code></pre></td></tr></table> +</div> +</div><p>复制工具库位置,以便 usbip 工具可以获取到:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0 +</span></span></code></pre></td></tr></table> +</div> +</div><p>安装 usb.ids 以便显示 USB 设备的名称:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo apt-get install hwdata +</span></span></code></pre></td></tr></table> +</div> +</div><p>重启WSL:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ wsl --shutdown +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面进行测试是否成功: +打开powershell:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl list +</span></span></code></pre></td></tr></table> +</div> +</div><p>假设我们需要在wsl使用的 usb 设备为 <code>ST-Link Debug, USB 大容量存储设备, USB 串行设备 (COM3)</code>,设备id为 <code>0483:374b</code></p> +<p>我们使用命令附加设备到 wsl2 中</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ usbipd wsl attach --hardware-id <span class="s2">&#34;0483:374b&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png.webp" +width="1200" +height="408" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/9f445ae61efe3fa9bf3ce333e0ce469d.png_huc102e1e211029c5cedda14d6097aac59_44184_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="294" +data-flex-basis="705px" +></p> +<p>此时我们打开一个 wsl 终端,使用命令 <code>lsusb</code> 即可看到附加到 wsl 的设备</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96.png" +width="1146" +height="310" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_480x0_resize_box_3.png 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/22478bf5a6a9981288f17be128919d96_hufea644602841bee6c7283a2b22a3e541_32967_1024x0_resize_box_3.png 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="369" +data-flex-basis="887px" +></p> +<p>然后我们再次回到 powershell ,执行 <code>usbipd wsl list</code>命令,可以看到此时的 usb 设备已经成功添加到 wsl 了</p> +<p><img src="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png.webp" +width="1200" +height="572" +srcset="https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_480x0_resize_q75_h2_box_2.webp 480w, https://kurisaw.github.io/p/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%ABwsl%E4%B8%AD%E4%BD%BF%E7%94%A8usb%E8%AE%BE%E5%A4%87/figure/b9d74353b8bcb2fbbbd2cd992ae9d8e9.png_hua939fa00c4e9286056c5c99bbb532251_65046_1024x0_resize_q75_h2_box_2.webp 1024w" +loading="lazy" +alt="screenshot_image.png" +class="gallery-image" +data-flex-grow="209" +data-flex-basis="503px" +></p> \ No newline at end of file diff --git a/tags/wsl/page/1/index.html b/tags/wsl/page/1/index.html new file mode 100644 index 000000000..27d210f0e --- /dev/null +++ b/tags/wsl/page/1/index.html @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/wsl/ + \ No newline at end of file diff --git "a/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.html" "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.html" new file mode 100644 index 000000000..ec9b3b0fa --- /dev/null +++ "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.html" @@ -0,0 +1,55 @@ +Tag: 二分查找 - kurisaW +

Tags

2 pages

二分查找

\ No newline at end of file diff --git "a/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.xml" "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.xml" new file mode 100644 index 000000000..9591999ea --- /dev/null +++ "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/index.xml" @@ -0,0 +1,977 @@ +二分查找 on kurisaWhttps://kurisaw.github.io/tags/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/Recent content in 二分查找 on kurisaWHugo -- gohugo.ioenThu, 16 Feb 2023 00:00:00 +0000【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\344\272\214\345\210\206\346\237\245\346\211\276/page/1/index.html" "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/page/1/index.html" new file mode 100644 index 000000000..c52f2836a --- /dev/null +++ "b/tags/\344\272\214\345\210\206\346\237\245\346\211\276/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/ + \ No newline at end of file diff --git "a/tags/\345\207\275\346\225\260/index.html" "b/tags/\345\207\275\346\225\260/index.html" new file mode 100644 index 000000000..992afa1da --- /dev/null +++ "b/tags/\345\207\275\346\225\260/index.html" @@ -0,0 +1,55 @@ +Tag: 函数 - kurisaW +

Tags

1 page

函数

\ No newline at end of file diff --git "a/tags/\345\207\275\346\225\260/index.xml" "b/tags/\345\207\275\346\225\260/index.xml" new file mode 100644 index 000000000..03dafa0e3 --- /dev/null +++ "b/tags/\345\207\275\346\225\260/index.xml" @@ -0,0 +1,776 @@ +函数 on kurisaWhttps://kurisaw.github.io/tags/%E5%87%BD%E6%95%B0/Recent content in 函数 on kurisaWHugo -- gohugo.ioenSun, 29 Aug 2021 00:00:00 +0000C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p> \ No newline at end of file diff --git "a/tags/\345\207\275\346\225\260/page/1/index.html" "b/tags/\345\207\275\346\225\260/page/1/index.html" new file mode 100644 index 000000000..9ad64e885 --- /dev/null +++ "b/tags/\345\207\275\346\225\260/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%87%BD%E6%95%B0/ + \ No newline at end of file diff --git "a/tags/\345\211\221\346\214\207offer/index.html" "b/tags/\345\211\221\346\214\207offer/index.html" new file mode 100644 index 000000000..7f9006b3f --- /dev/null +++ "b/tags/\345\211\221\346\214\207offer/index.html" @@ -0,0 +1,55 @@ +Tag: 剑指offer - kurisaW +

Tags

1 page

剑指offer

\ No newline at end of file diff --git "a/tags/\345\211\221\346\214\207offer/index.xml" "b/tags/\345\211\221\346\214\207offer/index.xml" new file mode 100644 index 000000000..4825278e1 --- /dev/null +++ "b/tags/\345\211\221\346\214\207offer/index.xml" @@ -0,0 +1,566 @@ +剑指offer on kurisaWhttps://kurisaw.github.io/tags/%E5%89%91%E6%8C%87offer/Recent content in 剑指offer on kurisaWHugo -- gohugo.ioenWed, 22 Feb 2023 00:00:00 +0000【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p> \ No newline at end of file diff --git "a/tags/\345\211\221\346\214\207offer/page/1/index.html" "b/tags/\345\211\221\346\214\207offer/page/1/index.html" new file mode 100644 index 000000000..10adf1345 --- /dev/null +++ "b/tags/\345\211\221\346\214\207offer/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%89%91%E6%8C%87offer/ + \ No newline at end of file diff --git "a/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.html" "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.html" new file mode 100644 index 000000000..fd89c34f5 --- /dev/null +++ "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.html" @@ -0,0 +1,56 @@ +Tag: 双指针法 - kurisaW +

Tags

6 pages

双指针法

\ No newline at end of file diff --git "a/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.xml" "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.xml" new file mode 100644 index 000000000..735c52f19 --- /dev/null +++ "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/index.xml" @@ -0,0 +1,3860 @@ +双指针法 on kurisaWhttps://kurisaw.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95/Recent content in 双指针法 on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/1/index.html" "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/1/index.html" new file mode 100644 index 000000000..7e7f89dd5 --- /dev/null +++ "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/2/index.html" "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/2/index.html" new file mode 100644 index 000000000..0522e2dc1 --- /dev/null +++ "b/tags/\345\217\214\346\214\207\351\222\210\346\263\225/page/2/index.html" @@ -0,0 +1,56 @@ +Tag: 双指针法 - Pager 2 - kurisaW +

Tags

6 pages

双指针法

\ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.html" "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.html" new file mode 100644 index 000000000..64878e3ac --- /dev/null +++ "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.html" @@ -0,0 +1,55 @@ +Tag: 哈希函数 - kurisaW +

Tags

1 page

哈希函数

\ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.xml" "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.xml" new file mode 100644 index 000000000..94ccca471 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/index.xml" @@ -0,0 +1,615 @@ +哈希函数 on kurisaWhttps://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E5%87%BD%E6%95%B0/Recent content in 哈希函数 on kurisaWHugo -- gohugo.ioenMon, 20 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\345\207\275\346\225\260/page/1/index.html" "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/page/1/index.html" new file mode 100644 index 000000000..063aa4abb --- /dev/null +++ "b/tags/\345\223\210\345\270\214\345\207\275\346\225\260/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E5%87%BD%E6%95%B0/ + \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.html" "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.html" new file mode 100644 index 000000000..97a5e6817 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.html" @@ -0,0 +1,55 @@ +Tag: 哈希碰撞 - kurisaW +

Tags

1 page

哈希碰撞

\ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.xml" "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.xml" new file mode 100644 index 000000000..736138ddd --- /dev/null +++ "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/index.xml" @@ -0,0 +1,615 @@ +哈希碰撞 on kurisaWhttps://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E7%A2%B0%E6%92%9E/Recent content in 哈希碰撞 on kurisaWHugo -- gohugo.ioenMon, 20 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\347\242\260\346\222\236/page/1/index.html" "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/page/1/index.html" new file mode 100644 index 000000000..67a90217e --- /dev/null +++ "b/tags/\345\223\210\345\270\214\347\242\260\346\222\236/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E7%A2%B0%E6%92%9E/ + \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\241\250/index.html" "b/tags/\345\223\210\345\270\214\350\241\250/index.html" new file mode 100644 index 000000000..155525a55 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\241\250/index.html" @@ -0,0 +1,55 @@ +Tag: 哈希表 - kurisaW +

Tags

2 pages

哈希表

\ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\241\250/index.xml" "b/tags/\345\223\210\345\270\214\350\241\250/index.xml" new file mode 100644 index 000000000..04e2087b7 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\241\250/index.xml" @@ -0,0 +1,1381 @@ +哈希表 on kurisaWhttps://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/Recent content in 哈希表 on kurisaWHugo -- gohugo.ioenTue, 21 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\241\250/page/1/index.html" "b/tags/\345\223\210\345\270\214\350\241\250/page/1/index.html" new file mode 100644 index 000000000..74b3359e0 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\241\250/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/ + \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.html" "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.html" new file mode 100644 index 000000000..a9ee682d2 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.html" @@ -0,0 +1,55 @@ +Tag: 哈希解法 - kurisaW +

Tags

1 page

哈希解法

\ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.xml" "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.xml" new file mode 100644 index 000000000..3d0f78665 --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/index.xml" @@ -0,0 +1,767 @@ +哈希解法 on kurisaWhttps://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A7%A3%E6%B3%95/Recent content in 哈希解法 on kurisaWHugo -- gohugo.ioenTue, 21 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\223\210\345\270\214\350\247\243\346\263\225/page/1/index.html" "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/page/1/index.html" new file mode 100644 index 000000000..8e6e7e11c --- /dev/null +++ "b/tags/\345\223\210\345\270\214\350\247\243\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%93%88%E5%B8%8C%E8%A7%A3%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\345\244\232\346\200\201\346\200\247/index.html" "b/tags/\345\244\232\346\200\201\346\200\247/index.html" new file mode 100644 index 000000000..4c86f51df --- /dev/null +++ "b/tags/\345\244\232\346\200\201\346\200\247/index.html" @@ -0,0 +1,55 @@ +Tag: 多态性 - kurisaW +

Tags

1 page

多态性

\ No newline at end of file diff --git "a/tags/\345\244\232\346\200\201\346\200\247/index.xml" "b/tags/\345\244\232\346\200\201\346\200\247/index.xml" new file mode 100644 index 000000000..120a5d75e --- /dev/null +++ "b/tags/\345\244\232\346\200\201\346\200\247/index.xml" @@ -0,0 +1,856 @@ +多态性 on kurisaWhttps://kurisaw.github.io/tags/%E5%A4%9A%E6%80%81%E6%80%A7/Recent content in 多态性 on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\244\232\346\200\201\346\200\247/page/1/index.html" "b/tags/\345\244\232\346\200\201\346\200\247/page/1/index.html" new file mode 100644 index 000000000..a4b7d6c7d --- /dev/null +++ "b/tags/\345\244\232\346\200\201\346\200\247/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%A4%9A%E6%80%81%E6%80%A7/ + \ No newline at end of file diff --git "a/tags/\345\255\227\347\254\246\344\270\262/index.html" "b/tags/\345\255\227\347\254\246\344\270\262/index.html" new file mode 100644 index 000000000..bc1c2b8f3 --- /dev/null +++ "b/tags/\345\255\227\347\254\246\344\270\262/index.html" @@ -0,0 +1,55 @@ +Tag: 字符串 - kurisaW +

Tags

2 pages

字符串

\ No newline at end of file diff --git "a/tags/\345\255\227\347\254\246\344\270\262/index.xml" "b/tags/\345\255\227\347\254\246\344\270\262/index.xml" new file mode 100644 index 000000000..686087faf --- /dev/null +++ "b/tags/\345\255\227\347\254\246\344\270\262/index.xml" @@ -0,0 +1,1223 @@ +字符串 on kurisaWhttps://kurisaw.github.io/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/Recent content in 字符串 on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p> \ No newline at end of file diff --git "a/tags/\345\255\227\347\254\246\344\270\262/page/1/index.html" "b/tags/\345\255\227\347\254\246\344\270\262/page/1/index.html" new file mode 100644 index 000000000..6be44ee9e --- /dev/null +++ "b/tags/\345\255\227\347\254\246\344\270\262/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/ + \ No newline at end of file diff --git "a/tags/\345\260\201\350\243\205\346\200\247/index.html" "b/tags/\345\260\201\350\243\205\346\200\247/index.html" new file mode 100644 index 000000000..734ae6ed9 --- /dev/null +++ "b/tags/\345\260\201\350\243\205\346\200\247/index.html" @@ -0,0 +1,55 @@ +Tag: 封装性 - kurisaW +

Tags

1 page

封装性

\ No newline at end of file diff --git "a/tags/\345\260\201\350\243\205\346\200\247/index.xml" "b/tags/\345\260\201\350\243\205\346\200\247/index.xml" new file mode 100644 index 000000000..c349d44a4 --- /dev/null +++ "b/tags/\345\260\201\350\243\205\346\200\247/index.xml" @@ -0,0 +1,856 @@ +封装性 on kurisaWhttps://kurisaw.github.io/tags/%E5%B0%81%E8%A3%85%E6%80%A7/Recent content in 封装性 on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\345\260\201\350\243\205\346\200\247/page/1/index.html" "b/tags/\345\260\201\350\243\205\346\200\247/page/1/index.html" new file mode 100644 index 000000000..ad49a06bd --- /dev/null +++ "b/tags/\345\260\201\350\243\205\346\200\247/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E5%B0%81%E8%A3%85%E6%80%A7/ + \ No newline at end of file diff --git "a/tags/\346\212\275\350\261\241\346\200\247/index.html" "b/tags/\346\212\275\350\261\241\346\200\247/index.html" new file mode 100644 index 000000000..7fd30d4d4 --- /dev/null +++ "b/tags/\346\212\275\350\261\241\346\200\247/index.html" @@ -0,0 +1,55 @@ +Tag: 抽象性 - kurisaW +

Tags

1 page

抽象性

\ No newline at end of file diff --git "a/tags/\346\212\275\350\261\241\346\200\247/index.xml" "b/tags/\346\212\275\350\261\241\346\200\247/index.xml" new file mode 100644 index 000000000..101bb671f --- /dev/null +++ "b/tags/\346\212\275\350\261\241\346\200\247/index.xml" @@ -0,0 +1,856 @@ +抽象性 on kurisaWhttps://kurisaw.github.io/tags/%E6%8A%BD%E8%B1%A1%E6%80%A7/Recent content in 抽象性 on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\346\212\275\350\261\241\346\200\247/page/1/index.html" "b/tags/\346\212\275\350\261\241\346\200\247/page/1/index.html" new file mode 100644 index 000000000..fb5297a15 --- /dev/null +++ "b/tags/\346\212\275\350\261\241\346\200\247/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E6%8A%BD%E8%B1%A1%E6%80%A7/ + \ No newline at end of file diff --git "a/tags/\346\214\207\351\222\210/index.html" "b/tags/\346\214\207\351\222\210/index.html" new file mode 100644 index 000000000..be72d9070 --- /dev/null +++ "b/tags/\346\214\207\351\222\210/index.html" @@ -0,0 +1,55 @@ +Tag: 指针 - kurisaW +

Tags

2 pages

指针

\ No newline at end of file diff --git "a/tags/\346\214\207\351\222\210/index.xml" "b/tags/\346\214\207\351\222\210/index.xml" new file mode 100644 index 000000000..9b9b4c856 --- /dev/null +++ "b/tags/\346\214\207\351\222\210/index.xml" @@ -0,0 +1,1843 @@ +指针 on kurisaWhttps://kurisaw.github.io/tags/%E6%8C%87%E9%92%88/Recent content in 指针 on kurisaWHugo -- gohugo.ioenSun, 29 Aug 2021 00:00:00 +0000C素养提升-函数专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/Sun, 29 Aug 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E5%87%BD%E6%95%B0%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-函数专题" /><p>函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。</p> +<p>一般形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; &lt;函数名称&gt;(&lt;形式参数说明&gt;)</p> +</blockquote> +<h2 id="函数的参数传递">函数的参数传递 +</h2><p>函数之间的参数传递方式:</p> +<ul> +<li>全局变量</li> +<li>复制传递方式</li> +<li>地址传递方式</li> +</ul> +<h4 id="1全局变量">1.全局变量 +</h4><p>全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。</p> +<p>全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。<code>不建议使用</code></p> +<h4 id="2复制传递">2.复制传递 +</h4><p>调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。</p> +<p><code>形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。</code></p> +<h4 id="3地址传递">3.地址传递 +</h4><p>按地址传递,实参为变量的地址,而形参为同类型的指针。</p> +<p>被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;welcome2023Jiangxi&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">str_fun</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;n=%d %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">str_fun</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">&lt;=</span> <span class="sc">&#39;z&#39;</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="sc">&#39;a&#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">num</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">-=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">num</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301311041301.png" +loading="lazy" +alt="image-20230131104155837" +></p> +<h2 id="函数的传参--数组">函数的传参&ndash;数组 +</h2><ul> +<li> +<p>全局数组传递方式</p> +</li> +<li> +<p>复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)</p> +</li> +<li> +<p>地址传递方式:实参为数组的指针,形参为同类型的指针变量</p> +</li> +</ul> +<h4 id="案例一">案例一 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="c1">//相当于int array_sum(int *data, int n); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">=</span> <span class="nf">array_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;sum=%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">array_sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">data</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="kt">int</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span><span class="o">--&gt;</span><span class="n">error</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021133075.png" +loading="lazy" +alt="image-20230202113334614" +></p> +<p>上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是<code>int data[]</code>,此时的<code>int data[]实际就是int *data</code>,使用<code>sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度</code>。</p> +<h4 id="案例二">案例二 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// try to write a function,which delete the space character of character string. +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;hello world,hello linux!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">del_space</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">str</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">str</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">str</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302021218836.png" +loading="lazy" +alt="image-20230202121727967" +></p> +<p>此处是删除一段字符串中的空格字符,在<code>void del_space()函数中,我们采取的是指针地址传递的形式</code>,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位<code>\0</code>时,代表字符串的末尾,因此我们也需要为赋值<code>*p = '\0';</code>代表末位。</p> +<h2 id="指针函数">指针函数 +</h2><h4 id="1基本概念">1.基本概念 +</h4><p>指针函数是指一个函数的<code>返回值为地址量</code>的函数。</p> +<h4 id="2定义形式">2.定义形式 +</h4><p>函数指针的定义的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">&lt;数据类型&gt;</span> <span class="err">*</span> <span class="err">&lt;函数名称&gt;(&lt;参数说明&gt;){</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">语句序列;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">`返回值:全局变量的地址</span> <span class="err">/</span> <span class="err">static变量的地址</span> <span class="err">/</span> <span class="err">字符串常量的地址</span> <span class="err">/</span> <span class="err">堆的地址`</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3示例">3.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个指针函数,删除一个字符串中的空格 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;How ar e y ou!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">del_space</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;----%s---</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">del_space</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141352422.png" +loading="lazy" +alt="image-20230214135249007" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,实现两个字符串的连接 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">dest</span><span class="p">[</span><span class="mi">59</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;welcome&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">src</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;makeru&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="nf">mstrcat</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span><span class="n">src</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="nf">mstrcat</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">dest</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">dest</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">src</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">dest</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">src</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141406595.png" +loading="lazy" +alt="image-20230214140618531" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一个函数,将传入的整型转成字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">s</span><span class="p">[</span><span class="mi">50</span><span class="p">],</span> <span class="o">*</span><span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="nf">itoa</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">r</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span> <span class="nf">itoa</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//static char p[50]; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141436801.png" +loading="lazy" +alt="image-20230214143612736" +></p> +<h2 id="递归函数">递归函数 +</h2><h4 id="1基本概念-1">1.基本概念 +</h4><p>递归函数是指一个函数的函数体中直接或间接调用了该函数自身</p> +<p>递归函数调用的执行过程分为两个阶段:</p> +<ul> +<li>递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。</li> +<li>回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。</li> +</ul> +<h4 id="2示例">2.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 计算n! +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;input:&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fac</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">fac</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141449368.png" +loading="lazy" +alt="image-20230214144903183" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,计算斐波那契序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141457841.png" +loading="lazy" +alt="image-20230214145721633" +></p> +<h2 id="函数指针">函数指针 +</h2><h4 id="1基本概念-2">1.基本概念 +</h4><p>函数指针<code>用来存放函数的地址</code>,这个地址是一个函数的入口地址</p> +<ul> +<li>函数名代表了函数的入口地址</li> +</ul> +<h4 id="2定义形式-1">2.定义形式 +</h4><p>函数指针变量说明的一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">数据类型</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*&lt;</span><span class="err">函数指针名称</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">(</span><span class="o">&lt;</span><span class="err">参数说明列表</span><span class="o">&gt;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nl">eg</span><span class="p">:</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3函数指针数组">3.函数指针数组 +</h4><p>定义:函数指针数组是一个保存若干个函数名的数组。</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">数据类型</span><span class="p">&gt;</span> (*<span class="p">&lt;</span><span class="nt">函数指针数组名称</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>)(<span class="p">&lt;</span><span class="nt">参数说明列表</span><span class="p">&gt;</span>); +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">---<span class="p">&lt;</span><span class="nt">大小</span><span class="p">&gt;</span>:指函数指针数组元素的个数 +</span></span><span class="line"><span class="cl">---其他等同普通的函数指针 +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4示例">4.示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 编写一段程序,实现qsort()排序的功能 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">89</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">54</span><span class="p">,</span> <span class="mi">75</span><span class="p">},</span> <span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">qsort</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="n">compare</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">compare</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302141730408.png" +loading="lazy" +alt="image-20230214173053208" +></p>C素养提升-指针专题https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/Tue, 29 Jun 2021 00:00:00 +0000https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/<img src="https://kurisaw.github.io/p/c%E7%B4%A0%E5%85%BB%E6%8F%90%E5%8D%87-%E6%8C%87%E9%92%88%E4%B8%93%E9%A2%98/cover.jpg" alt="Featured image of post C素养提升-指针专题" /><h2 id="指针">指针 +</h2><p>在c语言中,内存单元的地址成为指针,专门用来存放地址的变量,称为指针变量。</p> +<p>在不影响理解的情况中,有时对地址、指针和指针变量不区分,统称为指针。</p> +<h4 id="地址和变量">地址和变量 +</h4><p><code>在计算机内存中,每一个字节单元(Byte),都有一个编号,称为地址</code>。</p> +<p>编译或函数调用时为其分配内存单元。</p> +<p>变量是对程序中数据存储空间的抽象。</p> +<h4 id="指针变量的说明">指针变量的说明 +</h4><p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如,char *pName; +</span></span></code></pre></td></tr></table> +</div> +</div><p>指针的存储类型是指针变量本身的存储类型。</p> +<p>指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。</p> +<p>指针在说明的同时,也可以被赋值初值,成为指针的初始化</p> +<p>一般形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;存储类型&gt; &lt;数据类型&gt; * &lt;指针变量名&gt; = &lt;地址量&gt;; +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl">例如:int a, *pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>在上面的语句中,把变量a的地址作为初值赋了刚说明的int型指针pa。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">int a = 3; +</span></span><span class="line"><span class="cl">int *pa = &amp;a; //相当于:int * pa; pa = &amp;a; +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><em><strong>可以看到由于整型变量a取地址给指针变量p,最后打印可以发现这两个变量分配的地址都是<code>0x7fff64003e1c</code></strong></em></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121739386.png" +loading="lazy" +alt="image-20230112173909015" +></p> +<p>下面为了更清楚指针变量赋值与指针变量的地址,我们修改代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121750199.png" +loading="lazy" +alt="image-20230112175033147" +></p> +<p><em><strong>编译查看结果,可以发现上述的<code>p = &amp;a</code>是作为一个赋值操作,将a的地址赋值给了指针变量p,而指针变量本身还会分配一个地址单元,也就是上面显示的<code>0x7ffc915b44e0</code></strong></em></p> +<p>一般我们清楚,在指针中<code>*p</code>是作为取值,而<code>&amp;p</code>则是取地址,我们再次对程序作出修改:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p sizeof(p):%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %p %d </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121821672.png" +loading="lazy" +alt="image-20230112182106265" +></p> +<p><em><strong>那么我们可以看到<code>a = *p = *(*(&amp;p)) = 10</code>,仔细理解<code>*(*(&amp;p))</code>,也就是对p这个指针变量取地址之后再取值,此时所表示的意思其实一个地址量,也就是<code>p = *(&amp;p)</code>,此时对其取地址,可以发现和p所对应的地址相同,此时再对<code>*(*(&amp;p))</code>取值,那么也就是对应的一个数据,同理,<code>&amp;p = &amp;(*(&amp;p))</code>也就是指针变量p所占用存储区域的地址,作为一个系统随机默认分配的常量,这也是成立的。</strong></em></p> +<h4 id="指针的目标">指针的目标 +</h4><p>指针指向的内存区域中的数据成为指针的目标。</p> +<p>如果它指向的区域是程序中的一个变量的内存空间,则这个变量成为指针的目标变量。简称指针的目标。</p> +<p>在上述程序中,整型指针变量p所指向的就是整型变量a的内存空间,那么也可以称变量a是指针p的目标变量。</p> +<h4 id="引入指针">引入指针 +</h4><p>引入指针要注意程序中的px, *px和&amp;px三种表示方法的不同意义。设px为一个指针,则:</p> +<blockquote> +<p>px &mdash; 指针变量,它的内容是地址量</p> +</blockquote> +<blockquote> +<p>*px &mdash; 指针所指向的对象,它的内容是数据</p> +</blockquote> +<blockquote> +<p>&amp;px &mdash; 指针变量所占用的存储区域的地址,是个常量</p> +</blockquote> +<h4 id="指针的赋值">指针的赋值 +</h4><p>指针的赋值运算指的是通过赋值运算符指向指针变量送一个地址值。</p> +<p>向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能时普通的整数(除了赋零)</p> +<p>指针赋值运算常见的有以下几种形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1、把一个普通变量的地址赋给一个具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">px</span><span class="p">,</span> <span class="o">*</span><span class="n">py</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">px</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">py</span> <span class="o">=</span> <span class="n">px</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 3、把一个数据的地址赋给具有相同数据类型的指针: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">20</span><span class="p">],</span> <span class="o">*</span><span class="n">pa</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">pa</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> <span class="c1">//等价 pa = &amp;a[0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><p>下面是一个程序案例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span> <span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;p:%p a:%p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n\n</span><span class="s">&amp;q:%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">q</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">q</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="o">*</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301121941566.png" +loading="lazy" +alt="image-20230112194158128" +></p> +<p><em><strong>在上述程序中,我们将a的地址量分别传给指针p和指针q,然后打印这两个指针对应的地址,可以发现两者间相差8位<code>(一个指针在32位的计算机上,占4个字节;一个指针在64位的计算机上,占8个字节。此处由于我是64位系统,所以一个指针对应的就是8位,)</code>,也就是说指针p和指针q都是指向目标变量a。</strong></em></p> +<h4 id="指针运算">指针运算 +</h4><p>指针运算是以<code>指针变量所存放的地址量作为运算量而进行的运算</code>。</p> +<p>指针运算的<code>实质就是地址的计算</code>。</p> +<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">+</td> +<td style="text-align:center">px+n</td> +<td style="text-align:center">指针向地址大的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-n</td> +<td style="text-align:center">指针向地址小的方向移动n个数据</td> +</tr> +<tr> +<td style="text-align:center">++</td> +<td style="text-align:center">px++</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">&ndash;</td> +<td style="text-align:center">px&ndash;</td> +<td style="text-align:center">指针向地址小的方向移动1个数据</td> +</tr> +<tr> +<td style="text-align:center">-</td> +<td style="text-align:center">px-py</td> +<td style="text-align:center">两个指针之间相隔数据元素的个数</td> +</tr> +</tbody> +</table> +<ul> +<li> +<p>不同数据类型的两个指针实行加减整数运算是无意义的。</p> +</li> +<li> +<p>px+n表示的实际位置的地址量是:(px) + sizeof(px的类型)*n</p> +</li> +<li> +<p>px-n表示的实际位置的地址量是:(px) - sizeof(px的类型)*n</p> +</li> +<li> +<p>px-py运算的结果是两指针指向的地址位置之间相隔数据的个数,因此两指针相减不是两指针持有的地址量相减的结果,而是一个整数值,表示两指针之间相隔数据的个数。</p> +</li> +<li> +<p>两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。</p> +</li> +<li> +<p>指针与一般整型变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。</p> +</li> +</ul> +<p>注意:</p> +<p><code>两个指针之间的运算需要有连续的内存地址,否则会发生预想不到的错误</code>,示例如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122100423.png" +loading="lazy" +alt="image-20230112210030039" +></p> +<p>正确的运行示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122103226.png" +loading="lazy" +alt="image-20230112210312170" +></p> +<p><code>这里也可以与上面的知识点相对应:px-py运算的结果是两指针指向的地址位置之间相隔数据的个数</code></p> +<p>下面是一些指针运算的示例:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301122121416.png" +loading="lazy" +alt="image-20230112212116348" +></p> +<p>上述程序重要的就是理顺指针的关系以及运算符优先级问题。</p> +<hr> +<p>知识扩展:</p> +<p><strong>在32位系统与64位系统下,不同数据类型所对应的字节数&mdash;&gt;</strong></p> +<table> +<thead> +<tr> +<th style="text-align:center">数据类型</th> +<th style="text-align:center">32位</th> +<th style="text-align:center">64位</th> +<th style="text-align:center">备注</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center">char</td> +<td style="text-align:center">1</td> +<td style="text-align:center">1</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">short</td> +<td style="text-align:center">2</td> +<td style="text-align:center">2</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">int</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">32位与64位不同</td> +</tr> +<tr> +<td style="text-align:center">float</td> +<td style="text-align:center">4</td> +<td style="text-align:center">4</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">char *</td> +<td style="text-align:center">4</td> +<td style="text-align:center">8</td> +<td style="text-align:center">其他指针类型如long *,int *也是如此</td> +</tr> +<tr> +<td style="text-align:center">long long</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">double</td> +<td style="text-align:center">8</td> +<td style="text-align:center">8</td> +<td style="text-align:center"></td> +</tr> +<tr> +<td style="text-align:center">long double</td> +<td style="text-align:center">10/12</td> +<td style="text-align:center">10/16</td> +<td style="text-align:center">有效位10字节。32位为了对其实际分配12字节;64位分配16字节</td> +</tr> +</tbody> +</table> +<h2 id="指针与数组">指针与数组 +</h2><h4 id="指针对数组的访问">指针对数组的访问 +</h4><p>在c语言中,数组的指针是指数据在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。</p> +<p>一维数组的数组名为以为数组的指针(起始地址)。</p> +<p>例如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">x</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此,x为x数组的起始地址。</p> +<blockquote> +<p>设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:</p> +<p><strong><code>x[i]、*(px+i)、 *(x+i)和px[i]具有完全相同的功能,也就是说,x[i] = *(px+i) = *(x+i) = px[i]</code></strong>:访问数组第i+1个数组元素,下面参照示例:</p> +</blockquote> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131630839.png" +loading="lazy" +alt="image-20230113163021566" +></p> +<p>那么参照上述程序,在某种程度上p和a是否是等效的呢?其实这还是有区别的,数组a作为一个整型数组常量,而整型指针p则是一个变量,只能说在他们有相似的使用方法,这种情况还是需要区分的。</p> +<p><code>注意:</code></p> +<ul> +<li> +<p>指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量</p> +</li> +<li> +<p>但是指针变量和数组的指针(或叫数组名)在本质上不同,指针变量时地址变量,而数组的指针是地址常量</p> +</li> +</ul> +<h4 id="程序案例">程序案例 +</h4><p>程序1:下面编写一个程序,使用指针将整型数组中n个数按反序存放:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span> <span class="o">=*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">q</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">t</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">t</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131703949.png" +loading="lazy" +alt="image-20230113170338589" +></p> +<p>程序2</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">i</span><span class="p">),</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131710490.png" +loading="lazy" +alt="image-20230113171028194" +></p> +<p>这里我们发现,数组下标p[1]的本质,其实就是*(p+1),前面已经p++了,此时的p[1]其实就相当于 *(p+1+1),也就是 *p[2] = 2</p> +<p><strong>知识点:</strong></p> +<p><code>数组p[i],其实就相当于*(p+i),也就是:p[i] = *(p+i)</code></p> +<h2 id="指针与二维数组">指针与二维数组 +</h2><h4 id="二维数组的性质">二维数组的性质 +</h4><p>多维数组就是具有两个或两个以上下标的数组。</p> +<p>在c语言中,二维数组的元素连续存储,按行优先存取。</p> +<p>下面看程序案例:</p> +<p>案例一:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131739597.png" +loading="lazy" +alt="image-20230113173618278" +></p> +<p>上述程序中可以看出:a[0]为8个字节大小,所以可以看出数组名加1,移动的是一行元素。</p> +<p>案例二:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301131953543.png" +loading="lazy" +alt="image-20230113195318122" +></p> +<p>从上述程序中可以看出,a与a+1之间是相隔8个字节,而a[0]与a[0]+1则相隔4个字节,我们发现地址的移动步长发生变化了,原本是按行地址索引,加入指针即*a+1后,则变成了按列索引,更准确的说是原本的一行元素的索引变成了单个元素的索引。</p> +<h4 id="行指针数组指针">行指针(数组指针) +</h4><p><code>二维数组名代表数组的起始地址,数组名加1,是移动一行元素</code>。因此,<strong>二维数组名常被称为行地址</strong></p> +<p>**存储行地址的指针变量,叫做<code>行指针变量</code>。**形式如下:</p> +<blockquote> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; (*&lt;指针变量名&gt;)[表达式];</code></p> +<p>例如:int a[2] [3]; int (*p)[3]</p> +</blockquote> +<p><strong><code>注意:!!方括号中的常量表达式表示指针加1,移动几个数据。当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。</code></strong></p> +<p>我们用一个程序案例来解释:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">},</span> <span class="p">{</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">},</span> <span class="p">{</span><span class="mi">61</span><span class="p">,</span> <span class="mi">12</span><span class="p">}};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span> <span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span> <span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)),</span><span class="o">&amp;</span><span class="p">(</span><span class="o">*</span><span class="p">((</span><span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)));</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301132036861.png" +loading="lazy" +alt="image-20230113203626795" +></p> +<p>根据上述程序,其实就很好理解二维数组与数组指针的关系了,在二维数组中,对于指针的使用,一个取值符号*代表的其实就是行指针的地址量,而两个取值符号**代表的就是对行指针的第一个元素进行取值操作;同理,对一个地址量【 *(a+1)】进行取地址操作&amp;,代表的就是取地址【&amp;( *(a+1))】。</p> +<h2 id="字符指针与字符串">字符指针与字符串 +</h2><h4 id="字符指针的定义">字符指针的定义 +</h4><p>C语言通过使用字符数组来处理字符串。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。</p> +<h4 id="字符指针的初始化">字符指针的初始化 +</h4><p>**初始化字符指针是把内存中字符串的首地址赋予指针,**并不是把该字符串复制到指针中。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;Hell World&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">str</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在C编程中,<strong>当一个 字符指针指向一个字符串常量时,不能修改指针指向的对象的值。</strong></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="s">&#34;Hello World&#34;</span><span class="p">;</span> <span class="c1">//此处直接让一个字符指针等于字符串,其实存取的是这段字符串常量的首地址 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="sc">&#39;h&#39;</span><span class="p">;</span> <span class="c1">//错误,字符串常量不能修改 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-1">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p1</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">p2</span> <span class="o">=</span> <span class="s">&#34;hello world!&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p1=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">p1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;&amp;p2=%p %p %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p2</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141017174.png" +loading="lazy" +alt="image-20230114101732695" +></p> +<p>此处我们可以看到,由于字符指针的内容都是<code>hello world!</code>,也就是申请了一段字符串空间存取的内容为<code>hello world!</code>,当我们打印字符指针p1和p2指向的地址时可以发现都指向了<code>0x4006a4</code>,接着我们打印指针存放的地址,可以发现<code>&amp;p1=0x7ffc8d801cd8</code>、<code>&amp;p2=0x7ffc8d801ce0</code>,也就是说指针申请的空间都在栈中,而字符串常量空间的申请则是放在静态区**<code>(放在静态区的有三种情况:全局变量、static修饰的局部变量、常量)</code>**</p> +<h2 id="指针数组">指针数组 +</h2><h4 id="指针数组的定义">指针数组的定义 +</h4><p><strong>所谓指针数组是指若干个具有相同存储类型和数据类型的<code>指针变量</code>构成的集合。</strong></p> +<p>指针数组的一般说明形式:</p> +<blockquote> +<p>&lt;存储类型&gt; &lt;数据类型&gt; *&lt;指针数组名&gt;[&lt;大小&gt;];</p> +<p><strong>指针数组名表示该指针数组的起始地址</strong></p> +</blockquote> +<h4 id="指针数组的声明">指针数组的声明 +</h4><p>声明一个指针数组:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">double</span> <span class="o">*</span><span class="n">pa</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>把一维数组a[0]和a[1]的首地址分别赋予指针数组的数据元素pa[0]和pa[1]:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">pa</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//等价pa[0] = &amp;a[0][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">pa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">//等价pa[1] = &amp;a[1][0] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0],而pa[1]指向了一维数组a[1]的第一个元素a[1][0] +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="程序案例-2">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span><span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%p %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141118523.png" +loading="lazy" +alt="image-20230114111849051" +></p> +<blockquote> +<p>问:指针数组名相当于什么样的指针? 答:二级指针。</p> +</blockquote> +<h2 id="多级指针">多级指针 +</h2><h4 id="多级指针的定义">多级指针的定义 +</h4><p>把一个指向指针变量的指针变量,称为多级指针。</p> +<p>对于指向处理数据的指针变量称为一级指针变量,简称一级指针变量,简称一级指针。</p> +<p>对于指向一级指针的指针变量称为二级指针变量,简称一级指针变量,简称二级指针。</p> +<p>二级指针变量的说明形式如下:</p> +<p><code>&lt;存储类型&gt; &lt;数据类型&gt; **&lt;指针名&gt;;</code></p> +<h4 id="多级指针的运算">多级指针的运算 +</h4><p>**<code>指针变量加1,是向地址大的方向移动一个目标数据。</code>**类似的道理,多级指针运算也是以其目标变量为单位进行偏移。</p> +<p>比如:int **p; p+1移动一个int *变量所占的内存空间。</p> +<h4 id="程序案例-3">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">**</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="o">**</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141710805.png" +loading="lazy" +alt="image-20230114171007367" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;apple&#34;</span><span class="p">,</span> <span class="s">&#34;pear&#34;</span><span class="p">,</span> <span class="s">&#34;potato&#34;</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">),</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141723373.png" +loading="lazy" +alt="image-20230114172259973" +></p> +<h2 id="void指针">void指针 +</h2><h4 id="void指针的定义">void指针的定义 +</h4><p>void指针是一种不能确定数据类型的指针变量,它可以<code>通过强制类型转换让该变量指向任何数据类型的变量。</code></p> +<p>一般形式为:</p> +<blockquote> +<p>void * &lt;指针变量名&gt;</p> +</blockquote> +<p><strong><code>对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。</code></strong></p> +<h4 id="程序案例-4">程序案例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">n</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">m</span><span class="p">;</span> <span class="c1">//(void *) &amp;m +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">q</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">;</span> <span class="c1">//(void *)&amp;n +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%.2lf %.2lf</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">q</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141742757.png" +loading="lazy" +alt="image-20230114174233538" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span><span class="o">*</span><span class="p">((</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">p</span> <span class="o">+</span><span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202301141750626.png" +loading="lazy" +alt="image-20230114175011554" +></p> +<p>此处需要注意:对于void指针,在没有强制类型转换前,不能做任何指针的算数运算。所以在上述程序中对void指针的使用首先需要<code>(int *)p</code>进行强转,之后对于用户的算数运算就没什么问题了。</p> +<h2 id="const修饰指针">const修饰指针 +</h2><h4 id="常量化指针目标表达式">常量化指针目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>常量化指针目标是限制通过指针改变其目标的数值,<code>但&lt;指针变量&gt; ---&gt;存储的地址值可以修改。</code></p> +<h4 id="常量化指针变量">常量化指针变量 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>&lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p>使得&lt;指针变量&gt;存储的地址值不能修改。<code>但可以通过* &lt;指针变量名&gt;可以修改指针所指向变量的数值。</code></p> +<h4 id="常量化指针变量及目标表达式">常量化指针变量及目标表达式 +</h4><p>一般说明形式如下:</p> +<blockquote> +<p>const &lt;数据类型&gt; * const &lt;指针变量名&gt;[= &lt;指针运算表达式&gt;]</p> +</blockquote> +<p><code>常量化指针变量及目标表达式,使得既不可以修改&lt;指针变量名&gt;的地址,也不可以通过* &lt;指针变量名&gt;修改指针所指向变量的值。</code></p> \ No newline at end of file diff --git "a/tags/\346\214\207\351\222\210/page/1/index.html" "b/tags/\346\214\207\351\222\210/page/1/index.html" new file mode 100644 index 000000000..41ae9c837 --- /dev/null +++ "b/tags/\346\214\207\351\222\210/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E6%8C%87%E9%92%88/ + \ No newline at end of file diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" new file mode 100644 index 000000000..607a87b94 --- /dev/null +++ "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" @@ -0,0 +1,56 @@ +Tag: 数据结构 - kurisaW +

Tags

8 pages

数据结构

\ No newline at end of file diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.xml" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.xml" new file mode 100644 index 000000000..c452d7d61 --- /dev/null +++ "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.xml" @@ -0,0 +1,5039 @@ +数据结构 on kurisaWhttps://kurisaw.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/Recent content in 数据结构 on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/1/index.html" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/1/index.html" new file mode 100644 index 000000000..0ec5b98fc --- /dev/null +++ "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ + \ No newline at end of file diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/2/index.html" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/2/index.html" new file mode 100644 index 000000000..b16c1fced --- /dev/null +++ "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/page/2/index.html" @@ -0,0 +1,56 @@ +Tag: 数据结构 - Pager 2 - kurisaW +

Tags

8 pages

数据结构

\ No newline at end of file diff --git "a/tags/\346\225\260\347\273\204/index.html" "b/tags/\346\225\260\347\273\204/index.html" new file mode 100644 index 000000000..56e142d2e --- /dev/null +++ "b/tags/\346\225\260\347\273\204/index.html" @@ -0,0 +1,55 @@ +Tag: 数组 - kurisaW +

Tags

2 pages

数组

\ No newline at end of file diff --git "a/tags/\346\225\260\347\273\204/index.xml" "b/tags/\346\225\260\347\273\204/index.xml" new file mode 100644 index 000000000..7ac642c1f --- /dev/null +++ "b/tags/\346\225\260\347\273\204/index.xml" @@ -0,0 +1,977 @@ +数组 on kurisaWhttps://kurisaw.github.io/tags/%E6%95%B0%E7%BB%84/Recent content in 数组 on kurisaWHugo -- gohugo.ioenThu, 16 Feb 2023 00:00:00 +0000【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\346\225\260\347\273\204/page/1/index.html" "b/tags/\346\225\260\347\273\204/page/1/index.html" new file mode 100644 index 000000000..7f9ad385c --- /dev/null +++ "b/tags/\346\225\260\347\273\204/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E6%95%B0%E7%BB%84/ + \ No newline at end of file diff --git "a/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.html" "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.html" new file mode 100644 index 000000000..878befaab --- /dev/null +++ "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.html" @@ -0,0 +1,55 @@ +Tag: 暴力解法 - kurisaW +

Tags

2 pages

暴力解法

\ No newline at end of file diff --git "a/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.xml" "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.xml" new file mode 100644 index 000000000..68c8e2ac0 --- /dev/null +++ "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/index.xml" @@ -0,0 +1,977 @@ +暴力解法 on kurisaWhttps://kurisaw.github.io/tags/%E6%9A%B4%E5%8A%9B%E8%A7%A3%E6%B3%95/Recent content in 暴力解法 on kurisaWHugo -- gohugo.ioenThu, 16 Feb 2023 00:00:00 +0000【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\346\232\264\345\212\233\350\247\243\346\263\225/page/1/index.html" "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/page/1/index.html" new file mode 100644 index 000000000..df11dc236 --- /dev/null +++ "b/tags/\346\232\264\345\212\233\350\247\243\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E6%9A%B4%E5%8A%9B%E8%A7%A3%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.html" "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.html" new file mode 100644 index 000000000..e750fc6dd --- /dev/null +++ "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.html" @@ -0,0 +1,55 @@ +Tag: 环形链表 - kurisaW +

Tags

1 page

环形链表

\ No newline at end of file diff --git "a/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.xml" "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.xml" new file mode 100644 index 000000000..0073d5084 --- /dev/null +++ "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/index.xml" @@ -0,0 +1,628 @@ +环形链表 on kurisaWhttps://kurisaw.github.io/tags/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Recent content in 环形链表 on kurisaWHugo -- gohugo.ioenSat, 18 Feb 2023 00:00:00 +0000【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p> \ No newline at end of file diff --git "a/tags/\347\216\257\345\275\242\351\223\276\350\241\250/page/1/index.html" "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/page/1/index.html" new file mode 100644 index 000000000..6c94bc17d --- /dev/null +++ "b/tags/\347\216\257\345\275\242\351\223\276\350\241\250/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/ + \ No newline at end of file diff --git "a/tags/\347\256\227\346\263\225/index.html" "b/tags/\347\256\227\346\263\225/index.html" new file mode 100644 index 000000000..3a426c842 --- /dev/null +++ "b/tags/\347\256\227\346\263\225/index.html" @@ -0,0 +1,56 @@ +Tag: 算法 - kurisaW +

Tags

8 pages

算法

\ No newline at end of file diff --git "a/tags/\347\256\227\346\263\225/index.xml" "b/tags/\347\256\227\346\263\225/index.xml" new file mode 100644 index 000000000..b27cd082c --- /dev/null +++ "b/tags/\347\256\227\346\263\225/index.xml" @@ -0,0 +1,5039 @@ +算法 on kurisaWhttps://kurisaw.github.io/tags/%E7%AE%97%E6%B3%95/Recent content in 算法 on kurisaWHugo -- gohugo.ioenMon, 13 Mar 2023 00:00:00 +0000【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/Mon, 13 Mar 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B22kmp-%E5%AE%9E%E7%8E%B0-strstr-%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串2:KMP & 实现 strStr() & 重复的子字符串" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>KMP算法详解</li> +<li>28.实现 strStr()</li> +<li>459.重复的子字符串</li> +<li>字符串总结</li> +<li>双指针回顾</li> +</ul> +<h2 id="1kmp算法详解">1.KMP算法详解 +</h2><p>由于今天的算法题涉及到KMP算法,所以这里我们提前学习一下。</p> +<h4 id="1什么是kmp算法">(1)什么是KMP算法 +</h4><p>说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。</p> +<p>因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP。</p> +<h4 id="2kmp的作用">(2)KMP的作用 +</h4><p>KMP主要体现在<strong>字符串匹配</strong>上。</p> +<p>KMP算法的主要思想是<strong>当出现字符串不相匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头到尾再去匹配。</strong></p> +<p>因此如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。</p> +<h4 id="3什么是前缀表">(3)什么是前缀表 +</h4><p>前缀表有什么作用呢?</p> +<p><strong>前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配。</strong></p> +<p>其中我们会了解到next数组,<strong>next数组其实就是一个前缀表(prefix table)</strong>。</p> +<p>为了更加清楚地了解前缀表的来历,我们来举一个例子:</p> +<p><code>在文本串:aabaabaafa中查找是否出现过一个模式串:aabaaf。</code></p> +<p>如下面动画所示(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302251720943.gif" +loading="lazy" +alt="KMP精讲1" +></p> +<p>我们从上面的动画可以看出,文本串中第六个字符b和模式串的第六个个字符f已经不匹配了。如果暴力匹配的话,需要从头开始匹配;但是如果我们使用前缀表的话,就不会从头匹配,而是从上次已经匹配的内容开始匹配,也就是模式串中第三个字符b继续开始匹配。</p> +<p>那么<strong>前缀表时如何记录的呢?</strong></p> +<p>首先要知道前缀表的任务是当前任务匹配失败,找到之前已经匹配上的位置,再重新匹配,这也意味着再某个字符失配时,前缀表会告诉你,下一步匹配中,模式串应该跳到哪个位置。</p> +<p>所以前缀表的定义是:<strong>记录下标i之前(包含i)的字符串中,有多大长度的相同前缀后缀</strong>。</p> +<h4 id="4什么是最长公共前后缀">(4)什么是最长公共前后缀 +</h4><p>前文中字符串的前缀是指<strong>不包含最后一个字符的所有以第一个字符开头的连续子串</strong>。</p> +<p><strong>后缀</strong>是指<strong>不包含第一个字符的所有以最后一个字符结尾的连续子串</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262057510.png" +loading="lazy" +alt="image-20230226205706410" +></p> +<p>那么我们回到<strong>最长公共前后缀</strong>,更加准确的理解应该是“最长相等前后缀”,因为<strong>前缀表的要求就是相同前后缀</strong>。</p> +<p>而最长公共前后缀里面的“公共”,更像是在说前缀和后缀公共的长度。这其实并不是前缀表所需要的。</p> +<p>所以字符串a的最长相等前后缀为0;字符串aa的最长相等前后缀为1,字符串aaa的最长相等前后缀为2。</p> +<h4 id="5如何计算前缀表">(5)如何计算前缀表 +</h4><p>我们先来看几个例子:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252053992.png" +loading="lazy" +alt="image-20230225205304564" +></p> +<p>解说:长度为前1个字符的子串a,最长相同前后缀的长度为0.</p> +<p><code>注意:字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252058968.png" +loading="lazy" +alt="image-20230225205831598" +></p> +<p>解说:长度为前2个字符的子串aa,最长相同前后缀的长度为1.</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252102489.png" +loading="lazy" +alt="image-20230225210252121" +></p> +<p>解说:长度为前3个字符的子串aab,最长相同前后缀的长度为0.</p> +<p>&hellip;</p> +<p>以此类推:长度为前4个字符的子串aaba,最长相同前后缀的长度为1;长度为前5个字符的子串aabaa,最长相同前后缀的长度为2;长度为前6个字符的子串aabaaf,相同前后缀的长度为0.</p> +<p>最后把求得的最长相同前后缀的长度就是对应前后缀表的元素,如下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252131723.png" +loading="lazy" +alt="image-20230225213153188" +></p> +<p>可以看出模式串与前缀表对应位置的数字表示的就是:<strong>下标i之前(包括i)的字符串中,有多大长度的相同前后缀</strong>.</p> +<p>我们再来看下如何利用前缀表找到:当字符不匹配的时候指针应该移动的位置。如下动画所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302252329586.gif" +loading="lazy" +alt="KMP精讲2" +></p> +<p>当找到不匹配的位置,此时我们需要看它的前一个字符的前缀表的数值是多少。</p> +<p>之所以要前一个字符的前缀表的数值,是因为要找到前面字符串的最长相同的前后缀。</p> +<p>所以我们要看前一位的前缀表数值,动画中显示为2,所以将下标移动到下标2的位置继续匹配。直到在文本串中找到和模式串匹配的子串。</p> +<h4 id="5前缀表与next数组">(5)前缀表与next数组 +</h4><p>很多KMP算法的时间都是使用next数组做回退操作,那么next数组与前缀表有什么关系?</p> +<p>前面我们讲了,next数组其实就可以被认为是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)。</p> +<h4 id="6使用next数组匹配">(6)使用next数组匹配 +</h4><p>以下我们以前缀表统一减一之后的next数组来做演示。</p> +<p>注意此时的前缀表已经实现同一减一了,匹配动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302260850345.gif" +loading="lazy" +alt="KMP精讲4" +></p> +<h4 id="7时间复杂度分析">(7)时间复杂度分析 +</h4><p>其中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)</p> +<p>而暴力解法的时间复杂度明显是O(n * m),所以可知<strong>KMP在字符串匹配中极大地提高了搜索的效率</strong>。</p> +<h2 id="2leetcode28实现-strstr">2.Leetcode28.实现 strStr() +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;sadbutsad&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;sad&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;sad&#34;</span> <span class="err">在下标</span> <span class="mi">0</span> <span class="err">和</span> <span class="mi">6</span> <span class="err">处匹配。</span> +</span></span><span class="line"><span class="cl"><span class="err">第一个匹配项的下标是</span> <span class="mi">0</span> <span class="err">,所以返回</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">haystack</span> <span class="o">=</span> <span class="s">&#34;leetcode&#34;</span><span class="p">,</span> <span class="n">needle</span> <span class="o">=</span> <span class="s">&#34;leeto&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="s">&#34;leeto&#34;</span> <span class="err">没有在</span> <span class="s">&#34;leetcode&#34;</span> <span class="err">中出现,所以返回</span> <span class="o">-</span><span class="mi">1</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= haystack.length, needle.length &lt;= 104</li> +<li>haystack 和 needle 仅由小写英文字符组成</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前提说明:学习该小结需要提前对KMP算法有一定的了解,请详细阅读第一小节。</p> +<p>在本题目中,haystack(文本串),needle(模式串)。</p> +<p>解答此题目我们需要使用到KMP算法,那么使用KMP算法,需要我们构造next数组。</p> +<h6 id="1构造next数组">&lt;1&gt;构造next数组 +</h6><p>我们定义一个函数getNext来构建next数组,函数参数为指向next数组的指针,和一个字符串。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>**构造next数组其实就是计算模式串s、前缀表的过程。**主要有三步:</p> +<ul> +<li>1.初始化</li> +<li>2.处理前后缀不相同的情况</li> +<li>3.处理前后缀相同的情况</li> +</ul> +<p>下面我们来详细讲解:</p> +<p><strong>1.初始化</strong></p> +<p>定义了两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。</p> +<p>然后对next数组进行初始化赋值:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里之所以将j初始化为-1,是因为前面我们讲过前缀表要统一减一(当然也可以选择j不初始化为-1)</p> +<p>next[i]表示i(包括i)之前最长相等的前后缀长度(其实就是j)</p> +<p>所以初始化为next[0] = j;</p> +<p><strong>2.处理前后缀不相同的情况</strong></p> +<p>因为j初始化为-1,那么i就从1开始,并将s[i]与s[j + 1]进行比较。</p> +<p>所以遍历模式串s的循环下标i要从1开始,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与s[j + 1]不相同,也就是遇到前后缀末尾不相同的情况,就要向前回退。</p> +<p>这里我们再次明确一点:next[j]记录着j(包括j)之前的子串的相同前后缀的长度。</p> +<p>s[i]与s[j + 1]不相同,那么我们就要找一个j + 1前一个元素在next数组里的值(就是next[j])。</p> +<p>所以,处理前后缀不相同的情况的代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">//前后缀不相同的情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><code>注意:此处之所以写成while而不是if,是因为字符串回退并不是一步就可以的,而是一个连续回退的过程。</code></p> +<p><strong>3.处理前后缀相同的情况</strong></p> +<p>如果s[i]与s[j + 1]相同,那么就同时向后移动i和j说明找到了相同的前后缀,同时还要将j(前缀的长度)赋值给next[i],因为next[i]要记录相同前后缀的长度。如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>最后整体构建next数组的函数代码如下所示:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 前后缀不相同的时候 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋值给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>代码构造next数组的逻辑流程动画如下(来源:代码随想录):</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302262029303.gif" +loading="lazy" +alt="KMP精讲3" +></p> +<h6 id="2使用next数组进行匹配">&lt;2&gt;使用next数组进行匹配 +</h6><p>目标:在文本串中找是否出现过模式串t。</p> +<p>首先定义两个下标j指向模式串起始位置,i指向文本串起始位置。</p> +<p>此时j初始值依然为-1,因为next数组中记录的起始位置为-1.</p> +<p>i从0开始,遍历文本串,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>接下来就是s[i]与t[j + 1](因为从-1开始)进行比较。</p> +<p>如果s[i]与t[j + 1]不相同,就要从next数组中需按照下一个匹配的位置,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>如果s[i]与t[j + 1]相同,那么i和j同时向后移动,代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中定义 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>那么如何判断在文本串中出现了模式串t?如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了。</p> +<p>模式串出现的位置:当前在文本串匹配模式串的位置i减去模式串的长度。代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>因此使用next数组,用模式串匹配文本串的整体代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="c1">// 注意i从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]){</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)){</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表统一减一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i从1开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 前后缀不相同了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// 向前回退 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 找到相同的前后缀 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// 将j(前缀的长度)赋给next[i] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// // 因为next数组里记录的起始位置为-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 注意i就从0开始 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 不匹配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="c1">// j 寻找之前匹配的位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 匹配,j和i同时向后移动 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">j</span><span class="o">++</span><span class="p">;</span> <span class="c1">// i的增加在for循环里 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="c1">// 文本串s里出现了模式串t +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 前缀表(不减一) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nf">strStr</span><span class="p">(</span><span class="n">string</span> <span class="n">haystack</span><span class="p">,</span> <span class="n">string</span> <span class="n">needle</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">needle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">haystack</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">haystack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">needle</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">needle</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode459重复的子字符串">3.Leetcode459.重复的子字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/repeated-substring-pattern</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;ab&#34;</span> <span class="err">重复两次构成。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;aba&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcabcabcabc&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="err">可由子串</span> <span class="s">&#34;abc&#34;</span> <span class="err">重复四次构成。</span> <span class="p">(</span><span class="err">或子串</span> <span class="s">&#34;abcabc&#34;</span> <span class="err">重复两次构成。</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>对这道题我们有三种解决方法:暴力解法、移动匹配和KMP。</p> +<p>首先来看暴力解法,也就是一个for循环去获取子串的终止位置,再嵌套一个for循环判断子串是否能够重复构成字符串,所以时间复杂度为O(n^2)。</p> +<p>这里我们主要对移动匹配和KMP两种方法进行讲解。</p> +<h6 id="1移动匹配">&lt;1&gt;移动匹配 +</h6><p>首先我们来看题目,假设字符串s为:abcabc,内部由重复子串组成,那么该字符串的结构如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270903259.png" +loading="lazy" +alt="image-20230227090301956" +></p> +<p>那么既然前面有相同的子串,后面也有相同的子串,我们换个思路,是不是将后面的子串作为前串,前面的子串作为后串,这样一来是不是也能构成一个字符串s呢。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302270907324.png" +loading="lazy" +alt="image-20230227090746221" +></p> +<p>所以我们的思路就是:将两个s拼接起来,如果还能出现额外的一个s,那就说明该串是由重复子串构成。</p> +<p>这里为了避免在s+s搜索的时候搜索出原来的字符串s,这里我们需要进行<strong>掐头去尾</strong>(刨除s+s的首字符和尾字符),代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">repeatedSubstringPatterns</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">t</span> <span class="o">=</span> <span class="n">s</span> <span class="o">+</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">t</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 掐头去尾 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>虽然这个解法可行,但是后面我们还需要对字符串(s+s)是否出现过s做一个判断,在这个过程是增加了时间复杂度的算法成本的,例如使用库函数find、contains,一般的库函数的实现的时间复杂度为O(m + n)。</p> +<h6 id="2kmp">&lt;2&gt;KMP +</h6><p>想到KMP,就想到了KMP算法的字符串匹配,我们要在一个串中查找是否出现另外一个串,这才是KMP算法的专长所在.</p> +<p>代码如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">getNext</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">next</span><span class="p">,</span> <span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">next</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">next</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">repeatedSubstringPattern</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">next</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()];</span> +</span></span><span class="line"><span class="cl"> <span class="n">getNext</span><span class="p">(</span><span class="n">next</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">len</span> <span class="o">%</span> <span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">next</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4字符串总结">4.字符串总结 +</h2><p>对于本章节,涉及到很多经典的算法,最常见的就是双指针法,以及我们头疼的KMP算法(这部分其实我本人也没有很理解,需要反复理解)。</p>【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/Wed, 22 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%AD%97%E7%AC%A6%E4%B8%B21%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2i-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2ii-%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D-%E5%89%91%E6%8C%87offer%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/cover.jpg" alt="Featured image of post 【数据结构与算法】字符串1:反转字符串I & 反转字符串II &反转字符串里的单词 & 剑指offer(替换空格、左旋转字符串)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>344.反转字符串</li> +<li>541.反转字符串II</li> +<li>剑指Offer 05.替换空格</li> +<li>151.反转字符串里的单词</li> +<li>剑指Offer58-II.左旋转字符串</li> +</ul> +<h2 id="1leetcode344反转字符串">1.Leetcode344.反转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。</strong></p> +<p><strong>不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;o&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;o&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;l&#34;</span><span class="p">,</span><span class="s">&#34;e&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#34;H&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;h&#34;</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="s">&#34;h&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;n&#34;</span><span class="p">,</span><span class="s">&#34;a&#34;</span><span class="p">,</span><span class="s">&#34;H&#34;</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 105</li> +<li>s[i] 都是 ASCII 码表中的可打印字符</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>看到这道题的第一反应就是双指针法,不得不说,双指针法对这种排序问题真的YYDS,相比于我们前面在学习链表的时候所使用到的双指针法,字符串的反转其实比起链表还要简单一些。在内存中链表可以是无序的,但是字符串本质上也可以说的上是一种数组,所以元素在内存中是连续分布的。</p> +<p>那么对于这道题我们选择使用双指针法:分别定义指针i位于字符串下标0的位置和指针j位于字符串末尾的位置,通过互换元素的方式来完成字符串的反转。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221117397.png" +loading="lazy" +alt="image-20230222111753143" +></p> +<p>对应的部分C++代码:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span><span class="n">j</span><span class="o">--</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverseString</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode541反转字符串ii">2.Leetcode541.反转字符串II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-string-ii</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。</strong></p> +<ul> +<li>如果剩余字符少于 k 个,则将剩余字符全部反转。</li> +<li>如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacdfeg&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcd&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;bacd&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 仅由小写英文组成</li> +<li>1 &lt;= k &lt;= 104</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>我们在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。</p> +<p>该题主要需要解决两个问题:</p> +<ul> +<li>每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符</li> +<li>对于剩余字符如果不足k个则全部反转;如果在k ~ 2k之间,则反转剩余字符的前k个字符</li> +</ul> +<p>具体详细的解题步骤请看下图及代码:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221212235.png" +loading="lazy" +alt="image-20230222121250753" +></p> +<h4 id="3代码演示-1">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此处为用户设计的字符串反转,其实也就是Leetcode344题,当然我们也可以使用C++的reverse()函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseStr</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">))</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 1. 每隔 2k 个字符的前 k 个字符进行反转 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 3. 剩余字符少于 k 个,则将剩余字符全部反转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>reverse()</strong></p> +<ul> +<li>reverse函数功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include <!-- raw HTML omitted --></li> +<li>reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值</li> +</ul> +<h2 id="3剑指offer-05替换空格">3.剑指Offer 05.替换空格 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>请实现一个函数,把字符串 s 中的每个空格替换成&quot;%20&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;We are happy.&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;We%20are%20happy.&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>0 &lt;= s 的长度 &lt;= 10000</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>对这道题的求解,主要分三个步骤:</p> +<ul> +<li>首先扩充数组到每个空格替换成&quot;%20&quot;之后的大小</li> +<li>然后从后往前替换空格,也就是双指针法,如下图动画所示(来源:代码随想录)</li> +<li>i指向新长度的末尾,j指向旧长度的末尾</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221307960.gif" +loading="lazy" +alt="替换空格" +></p> +<p>而这里也有一个小技巧:<strong>遇到很多数组填充类的问题,都可以先预留给数组扩容带填充后的大小,然后再从后往前操作。</strong></p> +<p>这样做的好处:</p> +<ul> +<li>不用申请新数组</li> +<li>从后往前填充元素,避免了从前往后填充元素时都要讲添加元素之后的所有元素向后移动的问题。</li> +</ul> +<h4 id="3代码演示-2">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">replaceSpace</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计空格的个数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sOldSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 扩充字符串s的大小,也就是每个空格替换成&#34;%20&#34;之后的大小 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 之所以count * 2而不是 * 3,是因为之前的空格抵掉一个了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sNewSize</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 从后先前将空格替换为&#34;%20&#34; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sNewSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sOldSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;2&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;%&#39;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">-=</span> <span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>resize()</strong></p> +<ul> +<li>既分配了空间,也创建了对象。</li> +<li>这里空间就是capacity(指容器在分配新的存储空间之前能存储的元素总数),对象就是容器中的元素。</li> +</ul> +<h2 id="4leetcode151反转字符串里的单词">4.Leetcode151.反转字符串里的单词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-words-in-a-string</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个字符串 s ,请你反转字符串中 单词 的顺序。</strong></p> +<p><strong>单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。</strong></p> +<p><strong>返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。</strong></p> +<p><code>注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;the sky is blue&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;blue is sky the&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34; hello world &#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;world hello&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:反转后的字符串中不能存在前导空格和尾随空格。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">s</span> <span class="o">=</span> <span class="s">&#34;a good example&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="s">&#34;example good a&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length &lt;= 104</li> +<li>s 包含英文大小写字母、数字和空格 &rsquo; '</li> +<li>s 中 至少存在一个 单词</li> +</ul> +<p><strong>进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这样一道题,我们<strong>不使用辅助空间,空间复杂度要求为O(1)</strong></p> +<p>所以对此我们有这样一种解法:使用整体反转加局部反转的方式解决</p> +<ul> +<li>首先移除掉多余的空格</li> +<li>将整个字符串反转</li> +<li>再将每个单词反转</li> +</ul> +<p>演示如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221543326.png" +loading="lazy" +alt="image-20230222154346894" +></p> +<p>前面讲了整体的一个逻辑思维方式,那么代码怎么实现呢,首先我们看<strong>移除多余空格</strong>:我们的做法是<strong>通过快慢指针的方式来去除所有空格并且在相邻单词之间添加空格</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>此外就是字符串反转的问题,其代码实现逻辑如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 反转字符串s中左闭右闭的区间[start, end] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3代码演示-3">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">reverse</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span> <span class="c1">//翻转,区间写法:左闭右闭 [] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">end</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">s</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">removeExtraSpaces</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span><span class="c1">//去除所有空格并在相邻单词之间添加空格, 快慢指针。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//整体思想参考https://programmercarl.com/0027.移除元素.html +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//遇到非空格就处理,即删除所有空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span> <span class="c1">//手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//补上该单词,遇到空格说明单词结束。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">s</span><span class="p">[</span><span class="n">slow</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">s</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">slow</span><span class="p">);</span> <span class="c1">//slow的大小即为去除多余空格后的大小。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="nf">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">removeExtraSpaces</span><span class="p">(</span><span class="n">s</span><span class="p">);</span> <span class="c1">//去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span><span class="c1">// 反转字符串 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//removeExtraSpaces后保证第一个单词的开始下标一定是0。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//到达空格或者串尾,说明一个单词结束。进行翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//翻转,注意是左闭右闭 []的翻转。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//更新下一个单词的开始下标start +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5剑指offer58-ii左旋转字符串">5.剑指Offer58-II.左旋转字符串 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof</p> +</blockquote> +<h4 id="1题目-4">(1)题目 +</h4><p><strong>字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串&quot;abcdefg&quot;和数字2,该函数将返回左旋转两位得到的结果&quot;cdefgab&quot;。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;abcdefg&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;cdefgab&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;lrloseumgh&#34;</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="s">&#34;umghlrlose&#34;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>限制:</strong></p> +<ul> +<li>1 &lt;= k &lt; s.length &lt;= 10000</li> +</ul> +<h4 id="2思路-4">(2)思路 +</h4><p>在本题目中,carl老师继续升级难度:<strong>要求不能申请额外空间,只能在本串上操作</strong></p> +<p>但是对于上面Leetcode151题,我们依旧可以有借鉴之法,具体步骤如下:</p> +<ul> +<li>反转区间为前n的子串</li> +<li>反转区间为n到末尾的子串</li> +<li>反转整个字符串</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302221621199.png" +loading="lazy" +alt="image-20230222162131830" +></p> +<p>这样一来,整体的代码逻辑就特别简单啦!</p> +<h4 id="3代码演示-4">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">string</span> <span class="n">reverseLeftWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">s</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">s</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>没想到最后一个代码的实现这么简单哈哈哈,在经历<strong>Leetcode151.反转字符串里的单词</strong>这道题的洗礼后是不是有种小巫见大巫的想法。</p>【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/Tue, 21 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A82%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0ii-%E8%B5%8E%E9%87%91%E4%BF%A1-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表2:四数相加II & 赎金信 & 三数之和 & 四数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li>454.四数相加II</li> +<li>383.赎金信</li> +<li>15.三数之和</li> +<li>18.四数之和</li> +</ul> +<h2 id="1leetcode454四数相加ii">1.Leetcode454.四数相加II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum-ii</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:</strong></p> +<ul> +<li>0 &lt;= i, j, k, l &lt; n</li> +<li>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</li> +</ul> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="err">两个元组如下:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="mf">1.</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="mf">2.</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">nums1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums4</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>n == nums1.length</li> +<li>n == nums2.length</li> +<li>n == nums3.length</li> +<li>n == nums4.length</li> +<li>1 &lt;= n &lt;= 200</li> +<li>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>分析题意,题目中是四个独立数组,要求我们只要找到nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0,同时这四个数组长度相同,并且在本题目中并没有限制数组元素出现的次数,也就是说只要满足四数组元素相加为0都可以作为一组解。</p> +<p><strong>解题步骤:</strong></p> +<ul> +<li>首先定义一个unordered_map,key值为a、b两数之和,value值为a、b两数之和出现的次数。</li> +<li>遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。</li> +<li>定义int变量count,用来统计nums1 + nums2 + nums3 + nums4 = 0出现的次数。</li> +<li>在遍历nums3和nums4数组,找到如果0 - (nums3 + nums4)在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。</li> +<li>最后再返回统计值count就可以了。</li> +</ul> +<h4 id="3代码演示">(3)代码演示 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">fourSumCount</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums3</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums4</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">umap</span><span class="p">;</span> <span class="c1">// key:a+b的数值,value:a+b数值出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">a</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">umap</span><span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 统计nums1 + nums2 + nums3 + nums4 = 0出现的次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 在遍历nums3和nums4数组,找到如果 0-(nums3 + nums4) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">nums3</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="n">nums4</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">umap</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">))</span> <span class="o">!=</span> <span class="n">umap</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span> +</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">+=</span> <span class="n">umap</span><span class="p">[</span><span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">d</span><span class="p">)];</span><span class="c1">// 此处 umap[key]可以直接访问满足key的value值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode383赎金信">2.Leetcode383.赎金信 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/ransom-note</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。</strong></p> +<p><strong>如果可以,返回 true ;否则返回 false 。</strong></p> +<p><strong>magazine 中的每个字符只能在 ransomNote 中使用一次。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;a&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;b&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;ab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">ransomNote</span> <span class="o">=</span> <span class="s">&#34;aa&#34;</span><span class="p">,</span> <span class="n">magazine</span> <span class="o">=</span> <span class="s">&#34;aab&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= ransomNote.length, magazine.length &lt;= 105</li> +<li>ransomNote 和 magazine 由小写英文字母组成</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>首先锁定提示:两个字符串均由小写英文字母组成,并且magazine 中的每个字符只能在 ransomNote 中使用一次,这就跟战争时期的加密信件差不多一个意思,密信的内容在杂志中都可以找到。</p> +<p>对于这道题的解法,使用暴力解法,数组、map都可以实现,我们这里主要讲解暴力解法和数组,至于为什么不使用map,根据carl大神的说法就是<strong>这道题中使用map,空间消耗要比数组大一些,因为map需要维护红黑树或哈希表,并且还要做哈希函数,是很费时的</strong>,所以数组和map果断选择map。</p> +<p>暴力解法就是简单两层for循环,只要找到两个字符串中存在相同的字符就将ransomNote中对应的字符删去,直至最后ransomNote中无元素为止。</p> +<p>使用哈希解法的话,前面的学习我们也已经知道,数组也是一种简单的哈希表,通过定义一个record[26]的数组(因为条件说明仅为小写字母),首先遍历所有magazine中的元素对应record数组中的索引,出现相同的key值就将该value加一</p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n^2) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在ransomNote中找到和magazine相同的字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ransomNote</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">j</span><span class="p">);</span> <span class="c1">// ransomNote删除这个字符 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果ransomNote为空,则说明magazine的字符可以组成ransomNote +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4哈希解法">(4)哈希解法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度: O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">canConstruct</span><span class="p">(</span><span class="n">string</span> <span class="n">ransomNote</span><span class="p">,</span> <span class="n">string</span> <span class="n">magazine</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="c1">//add +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">ransomNote</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">magazine</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 通过recode数据记录 magazine里各个字符出现次数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">magazine</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">ransomNote</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历ransomNote,在record里对应的字符个数做--操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果小于零说明ransomNote里出现的字符,magazine没有 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">ransomNote</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="sc">&#39;a&#39;</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode15三数之和">3.Leetcode15.三数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/3sum</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。</strong></p> +<p><code>注意:答案中不可以包含重复的三元组。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-1,-1,2],[-1,0,1]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">不同的三元组是</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="err">和</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">注意,输出的顺序和三元组的顺序并不重要。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和不为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[0,0,0]]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:唯一可能的三元组和为</span> <span class="mi">0</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>3 &lt;= nums.length &lt;= 3000</li> +<li>-105 &lt;= nums[i] &lt;= 105</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>这道题和Leetcode454.四数相加II有点相似,不过在本题目中,特别限制了<strong>答案中不可包含重复的三元组</strong>。所以解题思路不能一概而论,同样可以使用<strong>哈希解法</strong>,但是现在目前最大的问题就是对三元组的去重工作,哈希解法的细节需要考虑的太多了,这里还是不建议使用,博主已经是晕了,当然大佬们可以尝试着理清关系。</p> +<p>那么另外一种解题思路就是使用<strong>双指针法</strong>。拿数组nums举例,首先将数组排序,元素i从下标0开始,同时设下一个下标 left 在 i + 1 的位置上,下标right在数组末尾,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212048396.png" +loading="lazy" +alt="image-20230221204834894" +></p> +<p>我们的目的是在数组nums中找到a、b、c,那么对于上图也就是a = nums[i], b = nums[left], c = nums[right]。由于我们提前排好序,所以此时abc相加会出现三种结果:</p> +<ul> +<li>nums[i] + nums[left] + nums[right] &gt; 0 :此时说明三数之和大了,需要我们将right下标向左移动</li> +<li>nums[i] + nums[left] + nums[right] = 0 :返回结果</li> +<li>nums[i] + nums[left] + nums[right] &lt; 0 :说明此时三数之和小了,需要我们将left下标向右移动</li> +</ul> +<p>此外,我们还需要解决去重的问题:</p> +<p><strong>&lt;1&gt;对a去重:</strong></p> +<p>按照一贯的理解我们可能是下面这种做法:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>但是我们看这种情况:如果我们这里选择上面的去重做法,当遍历第一个-1的时候,此时nums[i + 1]也就是-1,那么这组数据直接就被pass了,根据题意:<strong>返回不能有重复的三元组,但是三元组内的元素是可以重复的</strong>,如果按照上面的写法,那么我们很可能漏掉一组解。</p> +<p>所以应该是下面这段代码这样:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212052779.png" +loading="lazy" +alt="image-20230221205206723" +></p> +<p><strong>&lt;2&gt;b与c的去重:</strong></p> +<p>当我们收割到符合条件的结果的时候,如果不进行去重,可能会出现多个相同的结果,所以我们left和right会造成的相同结果进行去重,去重之后将两个指针再移动到一位进行比较。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212110982.png" +loading="lazy" +alt="image-20230221211026547" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212111616.png" +loading="lazy" +alt="image-20230221211127566" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212112023.png" +loading="lazy" +alt="image-20230221211223973" +></p> +<h4 id="3哈希解法">(3)哈希解法* +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[j], c = -(a + b) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> <span class="c1">//三元组元素a去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 三元组元素b去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">({</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">c</span><span class="p">});</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="c1">// 三元组元素c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4双指针法">(4)双指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找出a + b + c = 0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// a = nums[i], b = nums[left], c = nums[right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 错误去重a方法,将会漏掉-1,-1,2 这种情况 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> if (nums[i] == nums[i + 1]) { +</span></span></span><span class="line"><span class="cl"><span class="cm"> continue; +</span></span></span><span class="line"><span class="cl"><span class="cm"> } +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 正确去重a方法 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right&lt;=left 了,从而漏掉了 0,0,0 这种三元组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[right] == nums[right - 1]) right--; +</span></span></span><span class="line"><span class="cl"><span class="cm"> while (right &gt; left &amp;&amp; nums[left] == nums[left + 1]) left++; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode18四数之和">4.Leetcode18.四数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/4sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):</strong></p> +<ul> +<li> +<p>0 &lt;= a, b, c, d &lt; n</p> +</li> +<li> +<p>a、b、c 和 d 互不相同</p> +</li> +<li> +<p>nums[a] + nums[b] + nums[c] + nums[d] == target</p> +</li> +</ul> +<p><strong>你可以按 任意顺序 返回答案 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">8</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[2,2,2,2]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 200</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +</ul> +<h4 id="2思路-3">(2)思路 +</h4><p>这道题算的上是Leetcode15.三数之和的一个延伸,四数之和其实是在三数之和的基础上再外层再套了一层循环。</p> +<p>但是有些许细节需要我们认真对待:</p> +<ul> +<li>在三数之和中,target已经是定值0,但是在四数之和中,target可以是任意值,所以在某些地方我们可以对数组本身做一个剪枝操作。</li> +<li>在三数之和中的双指针解法是通过一层for循环nums[i]为确定值,然后循环内设置left和right下标作为双指针;而在四数之和中,我们要做的是<code>nums[k] + nums[i] + nums[left] + nums[right] == target</code>的所有可解集合,所以我们的解决方法是两层for循环<code>nums[k] + nums[i]</code>为确定值,双指针法依然是left和right作为下标。</li> +<li>三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302212146921.png" +loading="lazy" +alt="image-20230221214611511" +></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">fourSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 这里使用break,统一通过最后的return返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[k]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 2级剪枝处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[i]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">continue</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &gt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[k] + nums[i] + nums[left] + nums[right] &lt; target 会溢出 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">((</span><span class="kt">long</span><span class="p">)</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">{</span><span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 对nums[left]和nums[right]去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">left</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 找到答案时,双指针同时收缩 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">right</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div>【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】数组1:二分查找 & 移除元素https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/Wed, 15 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%841%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0/cover.jpg" alt="Featured image of post 【数据结构与算法】数组1:二分查找 & 移除元素" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>数组理论基础</p> +</li> +<li> +<p>704.二分查找</p> +</li> +<li> +<p>27.移除元素</p> +</li> +</ul> +<h2 id="1数组理论基础">1.数组理论基础 +</h2><p><strong>(1)数组是存放在连续内存空间上的相同类型数据的集合。</strong></p> +<p>注意:</p> +<ul> +<li>数组下标都是从0开始的</li> +<li>数组内存空间的地址是连续的</li> +</ul> +<p><strong>(2)正因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。</strong></p> +<p>例如删除下标为3的元素,我们需要堆下标为3的元素后面的所有元素都要做移动操作,如图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151124482.png" +loading="lazy" +alt="image-20230215112419117" +></p> +<p><strong>(3)数组的元素是不能删除的,只能使用覆盖的方式。</strong></p> +<p><strong>(4)C++中二维数组在地址空间上是连续的。</strong></p> +<p>通过编写一个程序来验证:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_arr</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="s">&#34; &#34;</span><span class="o">&lt;&lt;</span> <span class="o">&amp;</span><span class="n">array</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">test_arr</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151145095.png" +loading="lazy" +alt="image-20230215114525706" +></p> +<p>在C++中,一个int(整型)变量占据4个字节,所以相邻两个数组元素的地址差4个字节</p> +<h2 id="2leetcode704二分查找">2.Leetcode704:二分查找 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/binary-search</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="mi">4</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">9</span> <span class="err">出现在</span> <span class="n">nums</span> <span class="err">中并且下标为</span> <span class="mi">4</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">解释</span><span class="o">:</span> <span class="mi">2</span> <span class="err">不存在</span> <span class="n">nums</span> <span class="err">中因此返回</span> <span class="o">-</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>你可以假设 nums 中的所有元素是不重复的。</li> +<li>n 将在 [1, 10000]之间。</li> +<li>nums 的每个元素都将在 [-9999, 9999]之间。</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>首先确定关键词:</p> +<ul> +<li>数组为有序数组</li> +<li>数组无重复元素</li> +</ul> +<p>根据题目和提示,我们联想到二分法。</p> +<h4 id="3二分法">(3)二分法 +</h4><p>简单说下二分法,就是查找出特定元素(target)的位置,如果找到的话返回该元素的下标,如果没找到的话就返回-1。</p> +<p>关于二分法的写法,区间的定义一般分为两种:</p> +<ul> +<li>左闭右闭 [left, right]</li> +<li>左闭右开 [left, right)</li> +</ul> +<p>根据二分法的两种写法,我们分别求解:</p> +<p><strong>&lt;1&gt;第一种写法,我们定义target是在一个左闭右闭,也就是[left, right]</strong></p> +<p>区间的定义这就决定了二分法的代码如何编写,因为定义target在[left, right]区间,所以有如下两点:</p> +<ul> +<li>while(left &lt;= right) 要使用 &lt;=,因为left == right 是有意义的,所以使用 &lt;=</li> +<li>if (nums[middle] &gt; target) right要赋值为middle-1</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="err">首先我们确定使用的二分法的方法为左闭右闭,所以我们应该确定四个值:</span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">很明显</span> <span class="n">Left</span> <span class="o">=</span> <span class="err">数组下标</span><span class="mi">0</span> <span class="err">而</span><span class="n">Right为</span> <span class="n">NumSize</span><span class="p">(</span><span class="n">array</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="n">Middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">Left</span> <span class="o">+</span> <span class="n">Right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">所以编写如下函数:</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 因为我们此处允许左闭右闭,所以可能存在[1, 1],因此此处的left == right需要被考虑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 定义target在左闭右闭的区间里,[left, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当left==right,区间[left, right]依然有效,所以用 &lt;= +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span><span class="c1">// 防止溢出 等同于(left + right)/2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在左区间,所以[left, middle - 1] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,所以[middle + 1, right] +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;第二种写法,我们定义target是在一个左闭右开,也就是[left, right)</strong></p> +<p>根据左闭右开的方式,那么处理方式有如下两点:</p> +<ul> +<li>while(left &lt; right),这里使用 &lt;,因为left == right在区间 [left, right)是没有意义的</li> +<li>if(Num(middle) &gt; target) Num(right)更新为middle,因为当前的Num(middle)不等于Num(target),去左区间继续寻找,而寻找区间是左闭右开区间,那么也就是说下一和查询区间不会去比较Num(middle)</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 下面是一段伪代码形式来讲解 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="c1">// 首先我们确定使用的二分法的方法为左闭右开,所以我们应该确定四个值: +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">Left</span> <span class="o">|</span> <span class="n">Right</span> <span class="o">|</span> <span class="n">Middle</span> <span class="o">|</span> <span class="n">target</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="err">上面的定义不变,但是函数主体需要有一些改动了</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 注意:我们此处允许左闭右开,而不需要考虑右区间末值,此时的right = Num(array), +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第一种情况,当我们的middle值是明确大于target值时,此时我们更新right值为middle,因为此时的右区间为开区间,而此时的右区间不被考虑,所以Num(right) = Num(middle) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">right</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时我们考虑第二种情况,当我们的middle值是明确小于target值时,此时左区间为闭区间,我们更新left值为middle+1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">Num</span><span class="p">(</span><span class="n">target</span><span class="p">))</span> +</span></span><span class="line"><span class="cl"> <span class="n">Num</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">=</span> <span class="n">Num</span><span class="p">(</span><span class="n">middle</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 那么第三种情况也就是middle直接等于target,返回即可 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">else</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 版本二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 定义target在左闭右开的区间里,即:[left, right) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 因为left == right的时候,在[left, right)是无效的空间,所以使用 &lt; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">((</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// target 在左区间,在[left, middle)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// target 在右区间,在[middle + 1, right)中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// nums[middle] == target +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">middle</span><span class="p">;</span> <span class="c1">// 数组中找到目标值,直接返回下标 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 未找到目标值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>上面对二分法的两种方式都已经做出解释,分别提供了伪代码和程序代码,其中有些知识点在下方做出解释:</p> +<p><code>解析一:int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151439369.png" +loading="lazy" +alt="image-20230215143931951" +></p> +<p><strong>解答:对于上面这段代码做出这样修改的原因,主要就是为了防止溢出,如果在进行特别大的数值运算的时候,先进行加除操作很容易导致加法溢出最大限制,而首先进行减除操作则会大大降低风险。</strong></p> +<p><code>解析二:int middle = left + ((right - left) &gt;&gt; 1);</code></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302151443384.png" +loading="lazy" +alt="image-20230215144334277" +></p> +<p><strong>解答:<code>&gt;&gt;</code>是位运算的符号,<code>&gt;&gt;1</code>代表右移一位,这里我们记住尖号对准的方向就是位移方向。而对一个数右移一位,也就是代表除2操作。例如:11&raquo;1,将11转成二进制为1011,而对二进制数向右移动1位则变成了0101,也就是代表5,其实也就代表除2操作。</strong></p> +<p><strong>此外还要补充一下,从效率上看,使用移位指令有更高的效率,因为<code>移位指令占2个机器周期,而乘除法指令占4个机器周期</code>。从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。</strong></p> +<h2 id="3leetcode27移除元素">3.Leetcode27:移除元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-element</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。</strong></p> +<p><strong>不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。</strong></p> +<p><strong>元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</strong></p> +<p><strong>说明:</strong></p> +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> +<p>请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> +<p>你可以想象内部操作如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 在函数里修改输入数组对于调用者是可见的。 +</span></span></span><span class="line"><span class="cl"><span class="c1">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">print</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">2</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前两个元素均为</span> <span class="mi">2</span><span class="err">。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为</span> <span class="mi">2</span> <span class="err">,而</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">或</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span><span class="err">,也会被视作正确答案。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">5</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:函数应该返回新的长度</span> <span class="mi">5</span><span class="p">,</span> <span class="err">并且</span> <span class="n">nums</span> <span class="err">中的前五个元素为</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="err">。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>提示:</p> +<ul> +<li>0 &lt;= nums.length &lt;= 100</li> +<li>0 &lt;= nums[i] &lt;= 50</li> +<li>0 &lt;= val &lt;= 100</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>首先我们应该知道,在数组中,数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。</strong></p> +<p>对此我们使用<strong>暴力解法</strong></p> +<h4 id="3暴力解法">(3)暴力解法 +</h4><p>解法:通过使用两层for循环,一层for循环遍历数组元素,一层for循环更新数组。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">val</span><span class="p">){</span> <span class="c1">// 发现需要移除的元素,就将数组集体向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">nums</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">--</span><span class="err">;</span> <span class="c1">// 由于下标i以后的数值都向前移动了一位,所以i也向前移动一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">size</span><span class="o">--</span><span class="p">;</span> <span class="c1">// 相对应的数组大小-1 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:通过上面的程序可以看出暴力破解使用了两层for循环,也导致它的时间复杂度为O(n^2),通过遍历的形式找出目标值,并将目标值后一位前移覆盖掉目标值的形式,从而达到移除数组元素的目的。</strong></p> +<h4 id="4双指针法">(4)双指针法 +</h4><p>除了暴力解法,双指针法也同样适用于此场景。</p> +<p>通过定义两个指针,一个slow指针和一个fast指针, <strong>通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。</strong></p> +<ul> +<li>fast指针:寻找新数组的元素,新数组就是不含有目标元素的数组</li> +<li>slow指针:指向更新 新数组下标的位置</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 时间复杂度:O(n) +</span></span></span><span class="line"><span class="cl"><span class="c1">// 空间复杂度:O(1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">removeElement</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">slowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fastIndex</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">fastIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">!=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">])</span> <span class="p">{</span> <span class="c1">// 如果快指针指向的值不是目标值,则将快指针赋值给满指针,同时慢指针向前进一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">slowIndex</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fastIndex</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果找到目标值,则快指针继续向前移动一位,而慢指针不进行移位操作,这就不等同于暴力破解的覆盖了,而是重新对下标位置进行分配 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">slowIndex</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\347\256\227\346\263\225/page/1/index.html" "b/tags/\347\256\227\346\263\225/page/1/index.html" new file mode 100644 index 000000000..86ecc7a29 --- /dev/null +++ "b/tags/\347\256\227\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E7%AE%97%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\347\256\227\346\263\225/page/2/index.html" "b/tags/\347\256\227\346\263\225/page/2/index.html" new file mode 100644 index 000000000..38f03590f --- /dev/null +++ "b/tags/\347\256\227\346\263\225/page/2/index.html" @@ -0,0 +1,56 @@ +Tag: 算法 - Pager 2 - kurisaW +

Tags

8 pages

算法

\ No newline at end of file diff --git "a/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.html" "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.html" new file mode 100644 index 000000000..f9660a275 --- /dev/null +++ "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.html" @@ -0,0 +1,55 @@ +Tag: 类和对象 - kurisaW +

Tags

1 page

类和对象

\ No newline at end of file diff --git "a/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.xml" "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.xml" new file mode 100644 index 000000000..8692c2b60 --- /dev/null +++ "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/index.xml" @@ -0,0 +1,856 @@ +类和对象 on kurisaWhttps://kurisaw.github.io/tags/%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/Recent content in 类和对象 on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\347\261\273\345\222\214\345\257\271\350\261\241/page/1/index.html" "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/page/1/index.html" new file mode 100644 index 000000000..af01aebaf --- /dev/null +++ "b/tags/\347\261\273\345\222\214\345\257\271\350\261\241/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/ + \ No newline at end of file diff --git "a/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.html" "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.html" new file mode 100644 index 000000000..ecd6711c0 --- /dev/null +++ "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.html" @@ -0,0 +1,55 @@ +Tag: 线性探测法 - kurisaW +

Tags

1 page

线性探测法

\ No newline at end of file diff --git "a/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.xml" "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.xml" new file mode 100644 index 000000000..c690edb15 --- /dev/null +++ "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/index.xml" @@ -0,0 +1,615 @@ +线性探测法 on kurisaWhttps://kurisaw.github.io/tags/%E7%BA%BF%E6%80%A7%E6%8E%A2%E6%B5%8B%E6%B3%95/Recent content in 线性探测法 on kurisaWHugo -- gohugo.ioenMon, 20 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/page/1/index.html" "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/page/1/index.html" new file mode 100644 index 000000000..4a687aeb3 --- /dev/null +++ "b/tags/\347\272\277\346\200\247\346\216\242\346\265\213\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E7%BA%BF%E6%80%A7%E6%8E%A2%E6%B5%8B%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\347\273\247\346\211\277\346\200\247/index.html" "b/tags/\347\273\247\346\211\277\346\200\247/index.html" new file mode 100644 index 000000000..e8ba90d0a --- /dev/null +++ "b/tags/\347\273\247\346\211\277\346\200\247/index.html" @@ -0,0 +1,55 @@ +Tag: 继承性 - kurisaW +

Tags

1 page

继承性

\ No newline at end of file diff --git "a/tags/\347\273\247\346\211\277\346\200\247/index.xml" "b/tags/\347\273\247\346\211\277\346\200\247/index.xml" new file mode 100644 index 000000000..47b571af5 --- /dev/null +++ "b/tags/\347\273\247\346\211\277\346\200\247/index.xml" @@ -0,0 +1,856 @@ +继承性 on kurisaWhttps://kurisaw.github.io/tags/%E7%BB%A7%E6%89%BF%E6%80%A7/Recent content in 继承性 on kurisaWHugo -- gohugo.ioenSun, 19 Sep 2021 00:00:00 +0000Cplusplus-基础知识复习https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/Sun, 19 Sep 2021 00:00:00 +0000https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/<img src="https://kurisaw.github.io/p/cplusplus-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%A4%8D%E4%B9%A0/cover.jpg" alt="Featured image of post Cplusplus-基础知识复习" /><h2 id="基本格式">基本格式 +</h2><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hello world!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>编译预处理命令: <code>#include &lt;iostream&gt;</code>(输入输出流)</li> +<li>命令空间 <code>using namespace std;</code></li> +<li><code>cin &gt;&gt;</code> :用于输入;<code>cout &lt;&lt; </code>:用于输出; <code>endl</code>:用于换行</li> +<li>源文件扩展名.cpp +目标代码文件(编译后)扩展名.obj +可执行文件(链接后).exe</li> +</ul> +<h2 id="特点">特点 +</h2><ul> +<li>C++与C完全兼容,是C的扩展和改革</li> +<li>支持面向对象程序设计</li> +<li>生成的代码质量高</li> +<li>C++在C语言基础上引入了面向对象编程(OOP)的特性,它提供了类的概念,提供了OOP(和一些非OOP)语言中常见的四个特性:<strong>抽象、封装、继承和多态</strong>。</li> +</ul> +<h2 id="c数据类型">C++数据类型 +</h2><p>主要分为三类:基本数据类型、构造数据类型、类</p> +<h3 id="基本数据类型">基本数据类型 +</h3><ul> +<li>整型</li> +<li>实型(浮点型)</li> +<li>字符型</li> +<li>布尔型</li> +<li>void型</li> +</ul> +<h3 id="构造数据类型">构造数据类型 +</h3><ul> +<li>数组类型</li> +<li>指针类型</li> +<li>枚举类型</li> +<li>结构体类型</li> +<li>共用体类型</li> +</ul> +<h3 id="类">类 +</h3><ul> +<li>&hellip;</li> +</ul> +<h2 id="函数重载">函数重载 +</h2><p>简单来说,函数重载就是让功能相似的函数使用同一函数名,以增加程序的可读性。</p> +<p>如:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">area</span><span class="p">(</span><span class="kt">double</span> <span class="n">r</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>注意:如果函数重载和形参默认值同时出现,可能会引起歧义,应该避免这种情况发生</li> +</ul> +<h2 id="类和对象">类和对象* +</h2><h3 id="1类">1.类 +</h3><p>类由说明部分和实现部分组成,其说明部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="err">类名</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">2</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="err">成员表</span><span class="mi">3</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>实现部分的形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span><span class="o">::</span><span class="err">成员函数名(形参表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:<strong>在类内不能对数据成员进行初始化</strong>,同时,private\protect\public三个关键字对数据成员有不同的访问控制</p> +<ul> +<li>private:可以让数据成员变成私有成员,这些成员只能在类内使用,如果在类内没有写三个关键字的任意一个,则数据成员默认为私有成员;</li> +<li>public:可以让全数据成员变成共有成员,全部函数都能存取共有成员的数据,其定义了类的外部接口</li> +<li>protected:可以让数据成员变成保护成员,只有该类的函数,该类的派生类内的函数才能存取保护成员的数据</li> +</ul> +<h3 id="2类的成员函数">2.类的成员函数 +</h3><p>类的成员函数的定义一般在类外完成(也可以在类内完成),其形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类型</span> <span class="err">类名</span><span class="o">::</span><span class="err">函数成员名(参数表)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="err">函数体</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>其中::被称为作用域运算符,能指出函数成员是属于哪个类的</p> +<h3 id="3类的对象">3.类的对象 +</h3><h4 id="含义">含义 +</h4><p>如果把类看作是数据类型,则<strong>该数据类型定义的变量就是对象</strong>。</p> +<h4 id="格式">格式 +</h4><p>在定义类之后,就可以定义对象了,一般格式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">类名</span> <span class="err">对象名</span><span class="mi">1</span><span class="p">,</span><span class="err">对象名</span><span class="mi">2</span><span class="p">,...;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>也可以定义一个指向对象的指针,如Clock *p;则指针p指向Clock类的一个对象</p> +<h4 id="对象的使用">对象的使用 +</h4><p>对于一般对象(非对象指针),访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象名</span><span class="p">.</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>对于指向对象的指针,访问其成员的方式为:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">对象指针名</span><span class="o">-&gt;</span><span class="err">共有数据成员名</span><span class="p">(</span><span class="err">或共有成员函数名</span><span class="o">/</span><span class="err">参数表</span><span class="p">)</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>注意:其中<code>.</code>为点运算符;<code>-&gt;</code>为箭头运算符(类似结构体)</p> +<h4 id="示例">示例 +</h4><p>在主函数中调用Clock类中的show()函数,可写成如下形式:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">Clock</span> <span class="n">P</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">P</span><span class="p">;</span><span class="c1">//定义对象P以及指向P的指针p +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用对象P的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">P</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span> <span class="c1">//调用指针P指向的show()函数成员 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">).</span><span class="n">show</span><span class="p">();</span><span class="c1">//调用指针p指向的内容P的show()函数成员 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h2 id="类的访问权限">类的访问权限 +</h2><table> +<thead> +<tr> +<th style="text-align:left">继承方式</th> +<th style="text-align:left">基类的public成员</th> +<th style="text-align:left">基类的protected成员</th> +<th style="text-align:left">基类的private成员</th> +<th style="text-align:left">继承引起的访问控制关系变化概括</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:left">public继承</td> +<td style="text-align:left">仍为public成员</td> +<td style="text-align:left">仍为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员在子类的访问属性不变</td> +</tr> +<tr> +<td style="text-align:left">protected继承</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">变为protected成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类的非私有成员都为子类的保护成员</td> +</tr> +<tr> +<td style="text-align:left">private继承</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">变为private成员</td> +<td style="text-align:left">不可见</td> +<td style="text-align:left">基类中的非私有成员都称为子类的私有成员</td> +</tr> +</tbody> +</table> +<h2 id="构造函数与析构函数">构造函数与析构函数 +</h2><h3 id="1构造函数">1.构造函数 +</h3><h4 id="含义-1">含义 +</h4><p>构造函数的功能是将对象初始化,<strong>其特点是与类同名,且无返回类型</strong></p> +<h4 id="格式-1">格式 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="p">...</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">);</span> <span class="c1">//类中声明构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">...</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Clock</span><span class="o">::</span><span class="n">Clock</span><span class="p">(</span><span class="kt">int</span> <span class="n">newC</span><span class="p">,</span><span class="kt">int</span> <span class="n">newN</span><span class="p">,</span><span class="kt">int</span> <span class="n">newM</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">newC</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">newN</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">m</span> <span class="o">=</span> <span class="n">newM</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Clock</span> <span class="n">p</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//主函数中调用构造函数来初始化对象P +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">P</span><span class="p">.</span><span class="n">show</span><span class="p">();</span> <span class="c1">//对象P调用成员函数show()来完成其他目的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="2析构函数">2.析构函数 +</h3><h4 id="含义-2">含义 +</h4><p>类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。</p> +<p>析构函数的名称与类的名称时完全相同的,只是在前面加了一个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。</p> +<p><strong>只要类的对象被销毁,就会调用该类的析构函数。</strong></p> +<h4 id="作用">作用 +</h4><p>析构函数有利于在跳出程序(比如关闭文件、释放内存等)之前释放资源。</p> +<h4 id="示例-1">示例 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="nf">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">();</span> <span class="c1">//这是构造函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//这是析构函数声明 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being created&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;object is being deleted&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Line</span><span class="o">::</span><span class="n">setLength</span><span class="p">(</span><span class="kt">double</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">length</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">line</span><span class="p">.</span><span class="n">setLength</span><span class="p">(</span><span class="mf">6.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;length of line :&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">line</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//main函数返回前,line对象会被自动销毁 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="拷贝复制构造函数">拷贝(复制)构造函数 +</h2><h3 id="含义-3">含义 +</h3><p>拷贝构造函数时一种特殊的构造函数,其功能是用一个已知的对象去创建另一个同类对象。</p> +<p>拷贝构造函数常用于:</p> +<ul> +<li>通过使用另一个同类型的对象来初始化新创建的对象</li> +<li>复制对象把它作为参数传递给函数</li> +<li>复制对象,并从函数返回这个对象</li> +</ul> +<h3 id="格式-2">格式 +</h3><p>如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并由动态内存分配,则它必须有一个拷贝构造函数。</p> +<p>拷贝构造函数的常见形式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">classname</span> <span class="p">(</span><span class="k">const</span> <span class="n">classname</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 构造函数的主体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="拷贝构造函数的触发">拷贝构造函数的触发 +</h3><p>在C++中,主要有以下几种情况会调用拷贝构造函数:</p> +<h4 id="1使用一个同类型对象初始化另一个对象时">1.使用一个同类型对象初始化另一个对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj1</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj2</span><span class="p">(</span><span class="n">obj1</span><span class="p">);</span> <span class="c1">// 调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="2以值传递的方式将一个对象作为参数传递给函数时">2.以值传递的方式将一个对象作为参数传递给函数时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">myFunc</span><span class="p">(</span><span class="n">MyClass</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 函数接收到的obj是调用拷贝构造函数创建的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">myFunc</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="3返回局部对象时">3.返回局部对象时 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">myFunc</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">ret</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">ret</span><span class="p">;</span> <span class="c1">// 调用拷贝构造函数后返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4编译器优化时会让临时对象调用拷贝构造函数">4.编译器优化时会让临时对象调用拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">+</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// 两个临时对象会调用拷贝构造函数 +</span></span></span></code></pre></td></tr></table> +</div> +</div><h4 id="5在容器中插入一个新元素时会调用该元素的拷贝构造函数">5.在容器中插入一个新元素时会调用该元素的拷贝构造函数 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">MyClass</span><span class="o">&gt;</span> <span class="n">vec</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="n">MyClass</span> <span class="nf">obj</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">vec</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>以上主要情况会触发调用拷贝构造函数。熟悉这些情况,可以帮助诊断代码中拷贝构造的调用情况。</p> +<h3 id="示例-2">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Line</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">);</span> <span class="c1">//简单的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">);</span> <span class="c1">//拷贝构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="o">~</span><span class="n">Line</span><span class="p">();</span> <span class="c1">//析构函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 成员函数定义,包括构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="kt">int</span> <span class="n">len</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用构造函数&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 为指针分配内存 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::</span><span class="n">Line</span><span class="p">(</span><span class="k">const</span> <span class="n">Line</span> <span class="o">&amp;</span><span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;调用拷贝构造函数并为指针ptr分配内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ptr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">*</span><span class="n">obj</span><span class="p">.</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">//拷贝值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="n">Line</span><span class="o">::~</span><span class="n">Line</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;释放内存&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">Line</span><span class="o">::</span><span class="n">getLength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Line</span> <span class="n">obj</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;line 大小:&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span> <span class="o">&lt;&lt;</span> <span class="n">obj</span><span class="p">.</span><span class="n">getLength</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// 程序的主函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Line</span> <span class="n">line</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">display</span><span class="p">(</span><span class="n">line</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="友元函数">友元函数 +</h2><h3 id="含义-4">含义 +</h3><p>类的友元函数是定义在类外部,<strong>但有权访问类的所有私有(private)成员和保护(protected)成员。</strong></p> +<p>虽然友元函数的原型有在类的定义中出现过,但<strong>友元函数并不是成员函数。</strong></p> +<p>友元可以是一个函数,该函数称为友元函数;友元也可以是一个类,该类称为友元类,在这种情况下,整个类机器所有成员都是友元。</p> +<h3 id="格式-3">格式 +</h3><p>声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span><span class="lnt">9 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">length</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中进行声明,声明格式如下:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">friend</span> <span class="k">class</span> <span class="nc">ClassTwo</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="使用场景">使用场景 +</h3><p>C++友元函数的主要使用场景包括:</p> +<h4 id="1实现两个类之间的相互访问">1.实现两个类之间的相互访问 +</h4><p>如果类A需要访问类B的私有成员,可以将A声明为B的友元类,这样A就可以直接访问B的私有成员。</p> +<h4 id="2实现运算符重载">2.实现运算符重载 +</h4><p>重载像+、-等运算符时,需要访问类的私有成员,这时可以将运算符函数定义为类的友元。</p> +<h4 id="3模板类的访问">3.模板类的访问 +</h4><p>当类模板需要访问一个类的私有成员时,可以将这个类模板定义为该类的友元。</p> +<h4 id="4调试和测试类的实现">4.调试和测试类的实现 +</h4><p>在类的实现和测试阶段,可以使用友元函数方便地访问类的私有成员,以方便调试和测试。</p> +<h4 id="5避免繁琐的gettersetter方法">5.避免繁琐的getter/setter方法 +</h4><p>友元函数可以直接访问私有数据,避免定义许多getter和setter方法。</p> +<h4 id="6状态检查">6.状态检查 +</h4><p>友元函数可以方便地访问对象的状态,用于调试等目的。</p> +<p>需要注意的是,友元关系不可传递,过度使用友元会影响类的封装性。所以在保证必要的功能性的情况下,要优先使用公有接口,而非友元函数。</p> +<h3 id="示例-3">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Box</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">double</span> <span class="n">width</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="k">friend</span> <span class="kt">void</span> <span class="n">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">Box</span><span class="o">::</span><span class="n">setWidth</span><span class="p">(</span><span class="kt">double</span> <span class="n">wid</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="n">wid</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">//注意:printWidth()不是任何类的成员函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">printWidth</span><span class="p">(</span><span class="n">Box</span> <span class="n">box</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="cm">/* +</span></span></span><span class="line"><span class="cl"><span class="cm"> 因为printWidth()是Box的友元,它可以直接访问该类的任何成员 +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Width of box: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">box</span><span class="p">.</span><span class="n">width</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">Box</span> <span class="n">box</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">box</span><span class="p">.</span><span class="n">setWidth</span><span class="p">(</span><span class="mf">10.0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">printWidth</span><span class="p">(</span><span class="n">box</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="c内联函数">C++内联函数 +</h2><h3 id="含义-5">含义 +</h3><p>C++的内联函数通常是与类一起使用,如果一个函数是内联函数,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。</p> +<p>对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则会继续使用旧的函数。</p> +<p>如果想把一个函数定义为内联函数,则需要在函数名前放置inline关键字,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。</p> +<p>在类定义中定义的函数都是内联函数,即使没有使用inline关键字,也就是隐式内联。</p> +<h3 id="优缺点">优缺点 +</h3><ul> +<li> +<p>优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.</p> +</li> +<li> +<p>缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。</p> +</li> +<li> +<p>结论:一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!</p> +<p>另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行)。</p> +<p><strong>有些函数即使声明为内联的也不一定会被编译器内联</strong>, 这点很重要;比如虚函数和递归函数就不会被正常内联。</p> +<p>通常,递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数)。</p> +<p>虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.</p> +</li> +</ul> +<h3 id="示例-4">示例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">Max</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">)</span> <span class="o">?</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">y</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (20,10): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (0,200): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Max (100,1010): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">Max</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">1010</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h3 id="注意事项">注意事项 +</h3><ul> +<li>在内联函数中不允许使用循环语句和开关语句</li> +<li>内联函数的定义必须出现在内联函数第一次调用之前</li> +<li>类结构中所在的类说明内部定义的函数是内联函数</li> +</ul> +<h2 id="c-this指针">C++ this指针 +</h2><h3 id="含义-6">含义 +</h3><p>在C++中,this指针是一个特殊指针,它指向当前对象的实例。</p> +<p><strong>在C++中,每个对象都 能通过 this 指针来访问自己的地址。</strong></p> +<p>this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。</p> +<p>当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。</p> +<p><strong>友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针。</strong></p> +<h3 id="实例">实例 +</h3><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"> +</span></span></span><span class="line"><span class="cl"><span class="cp"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyClass</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">setValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">printValue</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Value: &#34;</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">MyClass</span> <span class="n">obj</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">setValue</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">obj</span><span class="p">.</span><span class="n">printValue</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\347\273\247\346\211\277\346\200\247/page/1/index.html" "b/tags/\347\273\247\346\211\277\346\200\247/page/1/index.html" new file mode 100644 index 000000000..235b578eb --- /dev/null +++ "b/tags/\347\273\247\346\211\277\346\200\247/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E7%BB%A7%E6%89%BF%E6%80%A7/ + \ No newline at end of file diff --git "a/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.html" "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.html" new file mode 100644 index 000000000..03d859d95 --- /dev/null +++ "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.html" @@ -0,0 +1,55 @@ +Tag: 螺旋矩阵 - kurisaW +

Tags

1 page

螺旋矩阵

\ No newline at end of file diff --git "a/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.xml" "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.xml" new file mode 100644 index 000000000..29180a0aa --- /dev/null +++ "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/index.xml" @@ -0,0 +1,474 @@ +螺旋矩阵 on kurisaWhttps://kurisaw.github.io/tags/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Recent content in 螺旋矩阵 on kurisaWHugo -- gohugo.ioenThu, 16 Feb 2023 00:00:00 +0000【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/Thu, 16 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E6%95%B0%E7%BB%842%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95-%E4%BA%8C%E5%88%86%E6%B3%95%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/cover.jpg" alt="Featured image of post 【数据结构与算法】数组2:双指针法 & 二分法(螺旋矩阵)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>977.有序数列的平方</p> +</li> +<li> +<p>209.长度最小的子数组</p> +</li> +<li> +<p>59.螺旋矩阵II</p> +</li> +</ul> +<h2 id="1leetcode977有序数列的平方">1.Leetcode977:有序数列的平方 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/squares-of-a-sorted-array</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">10</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:平方后,数组变为</span> <span class="p">[</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">排序后,数组变为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">100</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">11</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">121</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums.length &lt;= 104</li> +<li>-104 &lt;= nums[i] &lt;= 104</li> +<li>nums 已按 非递减顺序 排序</li> +</ul> +<p><strong>进阶:</strong></p> +<p>请你设计时间复杂度为 O(n) 的算法解决本问题</p> +<h4 id="2思路">(2)思路 +</h4><p>最开始的一个想法,就是首先对每个数进行平方,然后再对新数组进行排序。</p> +<h4 id="3暴力排序">(3)暴力排序 +</h4><p>有了昨天的经验,我们可以直接使用暴力排序的方式进行编程:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// nums[i] = pow(abs(nums[i]),2); +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">nums</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>说明:</strong></p> +<ul> +<li>pow(a,b):a作为目标值,b作为指数,是用作指数运算,例如pow(2,2)&mdash;&gt;2^2=4;</li> +<li>abs(n):对n求绝对值</li> +</ul> +<p><strong>解答:上面的求平方数我用了两种方式求解,但是很明显可以看出注释的那一段代码明显执行的时间复杂度更高,也就是O(nlogn+1+nlog2n),而另外的一种方式的时间复杂度则是O(n+nlogn)</strong></p> +<p>**在这里也有大佬提出:二分法的log2就直接logn就可以,平衡二叉树 排序都直接nlogn就行 **</p> +<h4 id="4双指针法">(4)双指针法 +</h4><p><strong>根据数组最大值通过平方之后,不是最大值就是最小值,我们可以考虑使用双指针法,i指向起始位置,j指向终止位置。</strong></p> +<ul> +<li>定义一个新数组result,和数组A一样的大小,让<code>K指向result数组终止位置</code></li> +<li>如果A[i] *A[i] &lt; A[j] * A[j],那么result[k&ndash;] = A[j] * A[j];</li> +<li>如果A[i] *A[i] &gt; A[j] * A[j],那么result[k&ndash;] = A[i] * A[i];</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sortedSquares</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">j</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">j</span><span class="p">;</span> <span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">[</span><span class="n">k</span><span class="o">--</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>通过双指针法求解有序数列的平方,此时的时间复杂度为O(n),相比较暴力排序这个还是更加推荐!</p> +<h2 id="2leetcode209长度最小的子数组">2.Leetcode209:长度最小的子数组 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/minimum-size-subarray-sum</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定一个含有 n 个正整数的数组和一个正整数 target 。</strong></p> +<p><strong>找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">7</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:子数组</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="err">是该条件下的长度最小的子数组。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">target</span> <span class="o">=</span> <span class="mi">11</span><span class="p">,</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="mi">0</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= target &lt;= 109</li> +<li>1 &lt;= nums.length &lt;= 105</li> +<li>1 &lt;= nums[i] &lt;= 105</li> +</ul> +<p><strong>进阶:</strong></p> +<p>如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。</p> +<h4 id="2思路-1">(2)思路 +</h4><p>首先分析题意,最明显的就是要求是<code>连续子数组</code>,然后就是要求这个子数组长度最小,遇到这个问题,我们想到的就是首先分出若干个有效子数组(要求是连续的),然后对这些子数组的长度进行筛选,留下长度最小的返回该数组长度。</p> +<h4 id="3暴力排序-1">(3)暴力排序 +</h4><p>对这道题暴力排序的解法是通过使用两个for循环,然后不断寻找符合条件的子序列,具体判断时间复杂度是O(n^2)。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> <span class="c1">// 最终的结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列起点为i +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 设置子序列终止位置为j +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 一旦发现子序列和超过了s,更新result +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">subLength</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span> <span class="c1">// 因为我们是找符合条件最短的子序列,所以一旦符合条件就break +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n^2)</li> +<li>空间复杂度:O(1)</li> +</ul> +<p><strong>对于这部分的暴力排序其实有些还没看懂,先在这插个眼,并且根据力扣的测试,该方法已经超时,应该是不建议使用。</strong></p> +<h4 id="4滑动窗口">(4)滑动窗口 +</h4><p><strong>所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们想要的结果。</strong></p> +<p>那怎么理解滑动窗口呢,其实滑动窗口的做法也可以作为双指针法的一种,通过动态变换滑动窗口的起始和终止位置构成的滑动区域,依次遍历可能出现的子数组。</p> +<p>这里放上Carl大神的一张图,方便大家理解:</p> +<p><img src="https://code-thinking.cdn.bcebos.com/gifs/209.%e9%95%bf%e5%ba%a6%e6%9c%80%e5%b0%8f%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84.gif" +loading="lazy" +alt="209.长度最小的子数组" +></p> +<p>那么最重要的两点来了:</p> +<ul> +<li>如何确定移动窗口的起始位置</li> +<li>如何确定移动窗口的结束位置</li> +</ul> +<p><strong>解答如下:</strong></p> +<ul> +<li>窗口的起始位置如何移动:如果当前窗口的值大于target,说明已经找到一种满足情况的子数组了,那么此时应该将窗口向前移动</li> +<li>窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是给定数组下标的最大值</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">INT32_MAX</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口数值之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">subLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 滑动窗口的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">subLength</span> <span class="o">=</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 取子序列的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">&lt;</span> <span class="n">subLength</span> <span class="o">?</span> <span class="nl">result</span> <span class="p">:</span> <span class="n">subLength</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span> <span class="c1">// 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">result</span> <span class="o">==</span> <span class="n">INT32_MAX</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">result</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>在这里的话也才发现滑动窗口这个算法精妙所在,通过不断变更一个窗口的位置,将算法的复杂度明显优化,而且相比较暴力排序,滑动窗口也只用了一个for循环和一个while循环,从而将算法复杂度降为O(n)</p> +<h2 id="3leetcode59螺旋矩阵ii">3.Leetcode59:螺旋矩阵II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/spiral-matrix-ii</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1,2,3],[8,9,4],[7,6,5]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="na">[[1]]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 20</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>在这里悉心听取Carl大神的教诲,每次遇到二分法一定要坚持<strong>循环不变量原则</strong>。</p> +<p>那么我们在模拟顺时针画矩阵时,遵循以下规则:</p> +<ul> +<li>填充上行从左往右</li> +<li>填充右列从上往下</li> +<li>填充下行从右往左</li> +<li>填充左列从下往上</li> +</ul> +<p>也就是如下图所示,好好理解一下!</p> +<p><img src="https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg" +loading="lazy" +alt="img" +></p> +<p>回到题目,对于这种螺旋矩阵,我们首先要明确的坚持<strong>循环不变量原则</strong>,要么选择左闭右闭,要么选择左闭右开,选择好一种处理方式就贯彻到底,不要再做改变了。</p> +<p><strong>这里我们选择左闭右开,首先还是看到上面的螺旋矩阵图,我们分别将3X3矩阵内的所有元素切割为9个部分,解决螺旋矩阵问题,最重要就是确定外围的四个点,即图中的<code>1、3、5、7</code>,前面我们说我们遵循左闭右开规则,其实意思就是对左节点进行处理,而右节点暂不处理,而等待下一次处理时将第一次的右节点作为第二次的左节点,这样就是我们所说的左闭右开原则。</strong></p> +<h4 id="3二分法求解">(3)二分法求解 +</h4><p>直接看代码部分:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">generateMatrix</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span> <span class="c1">// 使用vector定义一个二维数组 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">startx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">starty</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 定义每循环一个圈的起始位置 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 用来给矩阵中每一个空格赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 需要控制每一条边遍历的长度,每次循环右边界收缩一位 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">loop</span> <span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 下面开始的四个for就是模拟转了一圈 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 模拟填充上行从左到右(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">startx</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充右列从上到下(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充下行从右到左(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="n">starty</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 模拟填充左列从下到上(左闭右开) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">startx</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">startx</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">starty</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// offset 控制每一圈里每一条边遍历的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">offset</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">res</span><span class="p">[</span><span class="n">mid</span><span class="p">][</span><span class="n">mid</span><span class="p">]</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">res</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4总结">4.总结 +</h2><p><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93.png" +loading="lazy" +alt="img" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p> \ No newline at end of file diff --git "a/tags/\350\236\272\346\227\213\347\237\251\351\230\265/page/1/index.html" "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/page/1/index.html" new file mode 100644 index 000000000..02facbd3b --- /dev/null +++ "b/tags/\350\236\272\346\227\213\347\237\251\351\230\265/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/ + \ No newline at end of file diff --git "a/tags/\350\265\204\350\256\257/index.html" "b/tags/\350\265\204\350\256\257/index.html" new file mode 100644 index 000000000..387476cf8 --- /dev/null +++ "b/tags/\350\265\204\350\256\257/index.html" @@ -0,0 +1,55 @@ +Tag: 资讯 - kurisaW +

Tags

1 page

资讯

\ No newline at end of file diff --git "a/tags/\350\265\204\350\256\257/index.xml" "b/tags/\350\265\204\350\256\257/index.xml" new file mode 100644 index 000000000..dbebf95f3 --- /dev/null +++ "b/tags/\350\265\204\350\256\257/index.xml" @@ -0,0 +1,21 @@ +资讯 on kurisaWhttps://kurisaw.github.io/tags/%E8%B5%84%E8%AE%AF/Recent content in 资讯 on kurisaWHugo -- gohugo.ioenMon, 03 Apr 2023 00:00:00 +0000【资讯】汇总一些嵌入式相关的公司https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/Mon, 03 Apr 2023 00:00:00 +0000https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/<img src="https://kurisaw.github.io/p/%E8%B5%84%E8%AE%AF%E6%B1%87%E6%80%BB%E4%B8%80%E4%BA%9B%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%AC%E5%8F%B8/cover.jpg" alt="Featured image of post 【资讯】汇总一些嵌入式相关的公司" /><blockquote> +<p>来源:https://zhuanlan.zhihu.com/p/585079427</p> +</blockquote> +<h2 id="1芯片行业">1.芯片行业 +</h2><p>目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。</p> +<p>代表性公司:</p> +<p>(1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等</p> +<p>(2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等</p> +<h2 id="2人工智能相关行业">2.人工智能相关行业 +</h2><p>(1)自动驾驶方向也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。代表性的企业:小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。</p> +<p>(2)机器人方向机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。代表企业:大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等</p> +<h2 id="3消费电子行业">3.消费电子行业 +</h2><p>消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。代表性企业:华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等</p> +<h2 id="4传统汽车行业">4.传统汽车行业 +</h2><p>传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等</p> +<h2 id="5国企和军工">5.国企和军工 +</h2><p>国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。代表性企业:中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。</p> +<h2 id="6传统电子电器类">6.传统电子电器类 +</h2><p>这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。代表企业:美的、海尔、格力、TCL、海信等</p> +<h2 id="7网络及通信设备">7.网络及通信设备 +</h2><p>主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。代表企业:华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等</p> \ No newline at end of file diff --git "a/tags/\350\265\204\350\256\257/page/1/index.html" "b/tags/\350\265\204\350\256\257/page/1/index.html" new file mode 100644 index 000000000..6869b4500 --- /dev/null +++ "b/tags/\350\265\204\350\256\257/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E8%B5%84%E8%AE%AF/ + \ No newline at end of file diff --git "a/tags/\351\200\222\345\275\222\346\263\225/index.html" "b/tags/\351\200\222\345\275\222\346\263\225/index.html" new file mode 100644 index 000000000..106975529 --- /dev/null +++ "b/tags/\351\200\222\345\275\222\346\263\225/index.html" @@ -0,0 +1,55 @@ +Tag: 递归法 - kurisaW +

Tags

1 page

递归法

\ No newline at end of file diff --git "a/tags/\351\200\222\345\275\222\346\263\225/index.xml" "b/tags/\351\200\222\345\275\222\346\263\225/index.xml" new file mode 100644 index 000000000..1f5972d99 --- /dev/null +++ "b/tags/\351\200\222\345\275\222\346\263\225/index.xml" @@ -0,0 +1,834 @@ +递归法 on kurisaWhttps://kurisaw.github.io/tags/%E9%80%92%E5%BD%92%E6%B3%95/Recent content in 递归法 on kurisaWHugo -- gohugo.ioenFri, 17 Feb 2023 00:00:00 +0000【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\351\200\222\345\275\222\346\263\225/page/1/index.html" "b/tags/\351\200\222\345\275\222\346\263\225/page/1/index.html" new file mode 100644 index 000000000..9cdd5a883 --- /dev/null +++ "b/tags/\351\200\222\345\275\222\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E9%80%92%E5%BD%92%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.html" "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.html" new file mode 100644 index 000000000..15fdef3f4 --- /dev/null +++ "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.html" @@ -0,0 +1,55 @@ +Tag: 链地址法 - kurisaW +

Tags

1 page

链地址法

\ No newline at end of file diff --git "a/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.xml" "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.xml" new file mode 100644 index 000000000..5336459d7 --- /dev/null +++ "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/index.xml" @@ -0,0 +1,615 @@ +链地址法 on kurisaWhttps://kurisaw.github.io/tags/%E9%93%BE%E5%9C%B0%E5%9D%80%E6%B3%95/Recent content in 链地址法 on kurisaWHugo -- gohugo.ioenMon, 20 Feb 2023 00:00:00 +0000【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/Mon, 20 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%93%88%E5%B8%8C%E8%A1%A81%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D-%E4%B8%A4%E6%95%B0%E4%BA%A4%E9%9B%86-%E5%BF%AB%E4%B9%90%E6%95%B0-%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/cover.jpg" alt="Featured image of post 【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>哈希表理论基础</p> +</li> +<li> +<p>242.有效的字母异位词</p> +</li> +<li> +<p>349.两个数组的交集</p> +</li> +<li> +<p>202.快乐数</p> +</li> +<li> +<p>1.两数之和</p> +</li> +</ul> +<h2 id="1哈希表理论基础">1.哈希表理论基础 +</h2><h4 id="1哈希表">(1)哈希表 +</h4><p>哈希表(Hash table,国内也有一些书籍翻译为散列表):是<strong>根据关键码的值而直接访问的数据结构。</strong></p> +<p>最常见的哈希表例子就是数组。</p> +<p>哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201029762.png" +loading="lazy" +alt="image-20230220102916613" +></p> +<p>那么哈希表一般适用于哪些场景呢?<strong>一般哈希表都是用来快速判断一个元素是否出现在集合里。</strong></p> +<p>例如我们需要对指定商品信息进行查询,如果使用枚举的话,时间复杂度为O(n),但是如果我们选择使用哈希表,只需要O(1)就可以做到。</p> +<p>我们只需要初始化时将所有的商品名称存入哈希表,在查询的时候直接通过索引就可以知道该商品是否存在了。</p> +<p>这里将商品列表映射到哈希表上就涉及到<strong>哈希函数(Hash function)</strong>。</p> +<h4 id="2哈希函数">(2)哈希函数 +</h4><p>哈希函数,直接将商品的名称映射为哈希表上的索引,通过索引下标查询就可以知道该商品是否在售了。</p> +<p>哈希函数如下图所示,通过HashCode将名字转化为数值,一般HashCode是通过特定编码方式,可以将其他数据格式转化成不同的数值,这样就可以将商品名称映射到哈希表上的索引数字了。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201057379.png" +loading="lazy" +alt="image-20230220105717329" +></p> +<p>此时我们需要额外考虑一件事,如果通过hashCode得到的数值大于哈希表的大小,该怎么办?</p> +<p>为了保证映射出来的索引数值都落在哈希表上,我们会再一次对数值进行一个取模操作,这样我们就保证了商品名称就一定可以映射到哈希表上了。</p> +<p>此时由于哈希表本质上就是一个数组,如果商品的数量大于哈希表的大小该怎么办?哈希函数就算分的再均匀,也避免不了有几个商品名称同时映射到哈希表同一索引下标的位置。</p> +<p>这时候就需要引入<strong>哈希碰撞</strong>了。</p> +<h4 id="3哈希碰撞">(3)哈希碰撞 +</h4><p>如下图所示,商品1和商品3都映射到索引1的位置上,这个现象称之为<strong>哈希碰撞</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201128301.png" +loading="lazy" +alt="image-20230220112851251" +></p> +<p>对于哈希碰撞一般有两种解决方法:<strong>链地址法(拉链法)和线性探测法</strong></p> +<h4 id="4链地址法拉链法">(4)链地址法(拉链法) +</h4><p><em>这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。</em></p> +<p>由于商品1和商品3再索引2的位置发生了冲突,并且发生冲突的元素都被存储在链表中,这样我们就可以通过索引找到商品1和商品3了</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201138570.png" +loading="lazy" +alt="image-20230220113841529" +></p> +<h4 id="5线性探测法">(5)线性探测法 +</h4><p>使用线性探测法,一定要保证tableSize大于dataSize。我们需要依靠哈希表中的空位来解决碰撞问题。</p> +<p>例如索引1的位置已经存放了商品1的名称,那么当商品3再次进入索引1的位置就发生了冲突,当冲突发生后,就顺序查看表中的下一单元,直到找到一个空单元去存放商品3的名称。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201148846.png" +loading="lazy" +alt="image-20230220114854813" +></p> +<p>此外对于哈希碰撞的常用解决方法还有<strong>开放定址法、再哈希法、建立公共溢出区等等&hellip;</strong></p> +<h4 id="6常见的三种哈希结构">(6)常见的三种哈希结构 +</h4><p>当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构:</p> +<ul> +<li>数组</li> +<li>set(集合)</li> +<li>map(映射)</li> +</ul> +<p>数组在前面已经简单介绍了,此处不再赘述,我们看下set(集合):</p> +<p><strong>set(集合)</strong></p> +<p>在C++中,set和map分别提供以下三种数据结构,其底层优化以及优劣如下表所示:</p> +<table> +<thead> +<tr> +<th>集合</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::set</td> +<td>红黑树</td> +<td>有序</td> +<td>否</td> +<td>否</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::multiset</td> +<td>红黑树</td> +<td>有序</td> +<td>是</td> +<td>否</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::unordered_set</td> +<td>哈希表</td> +<td>无序</td> +<td>否</td> +<td>否</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<p><strong>map(映射)</strong></p> +<table> +<thead> +<tr> +<th>映射</th> +<th>底层实现</th> +<th>是否有序</th> +<th>数值是否可以重复</th> +<th>能否更改数值</th> +<th>查询效率</th> +<th>增删效率</th> +</tr> +</thead> +<tbody> +<tr> +<td>std::map</td> +<td>红黑树</td> +<td>key有序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(logn)</td> +<td>O(logn)</td> +</tr> +<tr> +<td>std::multimap</td> +<td>红黑树</td> +<td>key有序</td> +<td>key可重复</td> +<td>key不可修改</td> +<td>O(log n)</td> +<td>O(log n)</td> +</tr> +<tr> +<td>std::unordered_map</td> +<td>哈希表</td> +<td>key无序</td> +<td>key不可重复</td> +<td>key不可修改</td> +<td>O(1)</td> +<td>O(1)</td> +</tr> +</tbody> +</table> +<h4 id="7总结">(7)总结 +</h4><p><strong>当我们遇到这样一个场景:快速判断一个元素是否出现在集合里,就需要考虑哈希法。</strong></p> +<p>但是哈希法的缺点也显而易见的:<strong>牺牲空间去换取时间</strong>。</p> +<h2 id="2leetcode242有效的字母异位词">2.Leetcode242.有效的字母异位词 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/valid-anagram</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。</strong></p> +<p><code>注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;anagram&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;nagaram&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">true</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入</span><span class="o">:</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&#34;rat&#34;</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="s">&#34;car&#34;</span> +</span></span><span class="line"><span class="cl"><span class="err">输出</span><span class="o">:</span> <span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= s.length, t.length &lt;= 5 * 104</li> +<li>s 和 t 仅包含小写字母</li> +</ul> +<p><strong>进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?</strong></p> +<h4 id="2思路">(2)思路 +</h4><p>前面我们讲了数组其实就是一个简单的哈希表,在本题中,我们可以定义一个数组,来记录字符串s中出现的字符次数。</p> +<p>由于都是字母,对应的也就是26个字符,所以这里我们设置的数组长度为26即可,并且初始化为0.</p> +<p>例如,我们对字符串s = &ldquo;aee&rdquo;, t = &lsquo;&ldquo;eae&rdquo;,我们观察动画:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201724436.gif" +loading="lazy" +alt="242.有效的字母异位词" +></p> +<p>我们定义一个record的数组来记录字符串s里所有字符出现的次数。</p> +<p>需要将字符映射到数组也就是哈希表的下标上,字符a映射为下标0,字符z映射为下标25。</p> +<p><strong>在遍历字符串s的时候,只需要将s[i] = &lsquo;a&rsquo;所在的元素作+1操作即可;同时在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再作-1操作;最后再检查一下,record数组如果有的元素不为0,那么就说明字符t和字符s一定不互为字母异位词,return false.</strong></p> +<p><strong>最后如果record数组所有元素都为0,则说明字符s和字符t是字母异位词,return true。</strong></p> +<p><strong>时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)</strong></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">isAnagram</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">string</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">record</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">record</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">record</span><span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">&#39;a&#39;</span><span class="p">]</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">26</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// record数组所有元素都为零0,说明字符串s和t是字母异位词 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode349-两个数组的交集">3.Leetcode349. 两个数组的交集 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-arrays</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">nums2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">9</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span> <span class="err">也是可通过的</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= nums1.length, nums2.length &lt;= 1000</li> +<li>0 &lt;= nums1[i], nums2[i] &lt;= 1000</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>在这道题目中,需要我们掌握哈希数据结构:unordered_set,如下图所示:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201750667.png" +loading="lazy" +alt="image-20230220175039323" +></p> +<p>题目中特别声明:输出结果的每个元素一定是唯一的,也就是说输出的结果不用对重复出现的元素输出,同时可以不考虑输出结果的顺序。</p> +<p>之所以这里不使用数组,是因为题目限制了数组的大小,并且<strong>如果哈希值比较少、特别分散、跨度大,使用数组就会造成空间的极大浪费。</strong></p> +<p>所以结合<code>std::unordered_set</code>的无序性,查询效率和增删效率都是O(1)的情况下,果断使用unordered_set</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302201801586.png" +loading="lazy" +alt="image-20230220180154535" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums_set</span><span class="p">(</span><span class="n">nums1</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums1</span><span class="p">.</span><span class="n">end</span><span class="p">());</span><span class="c1">// 定义哈希表存放结果 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 发现nums2的元素 在nums_set里又出现过 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">nums_set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nums_set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> <span class="c1">// 在nums1中查找num(nums2) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span><span class="c1">// 如果发现与nums(nums2)的元素,向result_set插入该元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>当然这道题也可以使用数组的方式进行求解:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">intersection</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result_set</span><span class="p">;</span> <span class="c1">// 存放结果,之所以用set是为了给结果集去重 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">hash</span><span class="p">[</span><span class="mi">1005</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="c1">// 默认数值为0 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums1中出现的字母在hash数组中做记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// nums2中出现话,result记录 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">hash</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">result_set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">num</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result_set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result_set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode202快乐数">4.Leetcode202.快乐数 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/happy-number</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>编写一个算法来判断一个数 n 是不是快乐数。</strong></p> +<p>**「快乐数」 **定义为:</p> +<ul> +<li> +<p>对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。</p> +</li> +<li> +<p>然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</p> +</li> +<li> +<p>如果这个过程 结果为 1,那么这个数就是快乐数。</p> +</li> +</ul> +<p><code>如果 n 是 快乐数 就返回 true ;不是,则返回 false 。</code></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">19</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">true</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mi">92</span> <span class="o">=</span> <span class="mi">82</span> +</span></span><span class="line"><span class="cl"><span class="mi">82</span> <span class="o">+</span> <span class="mi">22</span> <span class="o">=</span> <span class="mi">68</span> +</span></span><span class="line"><span class="cl"><span class="mi">62</span> <span class="o">+</span> <span class="mi">82</span> <span class="o">=</span> <span class="mi">100</span> +</span></span><span class="line"><span class="cl"><span class="mi">12</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">+</span> <span class="mo">02</span> <span class="o">=</span> <span class="mi">1</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="nb">false</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>1 &lt;= n &lt;= 231 - 1</li> +</ul> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题目所给出的提示:<strong>重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。</strong></p> +<p>简单解释下这句话,那么我们是不是可以理解为如果存在循环的数的话,那么这是不是就说明这个数不是开心数?</p> +<p>那么对于判断是否存在重复出现的数,我们选择使用哈希法,如果重复了的话就返回false,否则一直找到sum = 1为止。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 取数值各个位上的单数平方之和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">getSum</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">sum</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">10</span><span class="p">);</span> <span class="c1">// n每位数的平方和 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">10</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="nf">isHappy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">getSum</span><span class="p">(</span><span class="n">n</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// 记录第一次出现的数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5leetcode1两数之和">5.Leetcode1.两数之和 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/two-sum</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。</strong></p> +<p><strong>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</strong></p> +<p><strong>你可以按任意顺序返回答案。</strong></p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:因为</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">9</span> <span class="err">,返回</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>2 &lt;= nums.length &lt;= 104</li> +<li>-109 &lt;= nums[i] &lt;= 109</li> +<li>-109 &lt;= target &lt;= 109</li> +<li>只会存在一个有效答案</li> +</ul> +<p><strong>进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>根据提示:只存在一个有效答案。所以我们这里可以选择<strong>unordered_map</strong></p> +<p>接下来我们明确两点:</p> +<ul> +<li>map用来做什么</li> +<li>map中key和value分别表示什么</li> +</ul> +<p><strong>拿target = 9举例子:map的目的是用来存取我们访问过的元素,当我们遍历数组的时候,需要我们记录之前遍历过哪些元素和对应的下标,首先先选定一个值(比如2),通过map查询是否存在与之满足条件的符合 因子(只能是7),此时如果在map中索引到该值,那么就得出我们想要的结果了;如果没有则继续选定下一个值,再去寻找与之相对应的符合因子。</strong></p> +<p>所以在<strong>map中的存储结构为:{key:数据元素, value:数组元素对应的下标}</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202101163.png" +loading="lazy" +alt="image-20230220210132750" +></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302202116179.png" +loading="lazy" +alt="image-20230220211643116" +></p> +<h4 id="3代码实现-3">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">twoSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span> <span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">map</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历当前元素,并在map中寻找是否有匹配的key +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">auto</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">iter</span> <span class="o">!=</span> <span class="n">map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="n">iter</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">i</span><span class="p">};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 如果没找到匹配对,就把访问过的元素和下标加入到map中 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">map</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span><span class="p">));</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{};</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\351\223\276\345\234\260\345\235\200\346\263\225/page/1/index.html" "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/page/1/index.html" new file mode 100644 index 000000000..739da1c5d --- /dev/null +++ "b/tags/\351\223\276\345\234\260\345\235\200\346\263\225/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E9%93%BE%E5%9C%B0%E5%9D%80%E6%B3%95/ + \ No newline at end of file diff --git "a/tags/\351\223\276\350\241\250/index.html" "b/tags/\351\223\276\350\241\250/index.html" new file mode 100644 index 000000000..988d5bf83 --- /dev/null +++ "b/tags/\351\223\276\350\241\250/index.html" @@ -0,0 +1,55 @@ +Tag: 链表 - kurisaW +

Tags

2 pages

链表

\ No newline at end of file diff --git "a/tags/\351\223\276\350\241\250/index.xml" "b/tags/\351\223\276\350\241\250/index.xml" new file mode 100644 index 000000000..95b4e1563 --- /dev/null +++ "b/tags/\351\223\276\350\241\250/index.xml" @@ -0,0 +1,1461 @@ +链表 on kurisaWhttps://kurisaw.github.io/tags/%E9%93%BE%E8%A1%A8/Recent content in 链表 on kurisaWHugo -- gohugo.ioenSat, 18 Feb 2023 00:00:00 +0000【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/Sat, 18 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A82%E8%8A%82%E7%82%B9%E4%BA%A4%E6%8D%A2%E4%B8%8E%E5%88%A0%E9%99%A4-%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8/cover.jpg" alt="Featured image of post 【数据结构与算法】链表2:节点交换与删除 & 链表相交 & 环形链表" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>24.两两交换链表中的节点</p> +</li> +<li> +<p>19.删除链表的倒数第N个节点</p> +</li> +<li> +<p>面试题02.07.链表相交</p> +</li> +<li> +<p>142.环形链表II</p> +</li> +<li> +<p>总结</p> +</li> +</ul> +<h2 id="1leetcode24两两交换链表中的节点">1.Leetcode24:两两交换链表中的节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/swap-nodes-in-pairs</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181041283.png" +loading="lazy" +alt="image-20230218104104240" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目在范围 [0, 100] 内</li> +<li>0 &lt;= Node.val &lt;= 100</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p>前面我们有了链表的相关基础知识,知道了对于链表节点的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p>相比较第一种,第二种虚拟头节点的形式更加方便。</p> +<p><strong>初始时,cur指向虚拟头节点,然后依次进行三步:</strong></p> +<ul> +<li><code>步骤1:将原链表的头节点变成节点2</code></li> +<li><code>步骤2:将原链表的节点2变成一个临时节点tmp(tmp:指向原链表的头节点)</code></li> +<li><code>步骤3:将原链表的节点3变成一个临时节点tmp2(tmp2:指向原链表的节点3)(ps:此处这样重复定义是为了后续循环条件的退出)</code></li> +<li><code>ps:原链表:未加入虚拟头节点的链表,也就是初始化时的链表</code></li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181114718.png" +loading="lazy" +alt="image-20230218111454677" +></p> +<p>操作后的链表:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181115102.png" +loading="lazy" +alt="image-20230218111528059" +></p> +<p><strong>终止条件:</strong></p> +<p><code>当cur节点经过第一轮循环时,说明这个链表至少有2个节点,此时cur已经成了原链表的节点2,再进行下一次循环时,如果还有新的节点,只要满足cur节点之后还存在1个或2个节点,循环继续,否则结束循环,并返回原链表的头节点</code></p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">swapPairs</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的头节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 记录临时节点,原本的节点3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 步骤一 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 步骤二 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">tmp1</span><span class="p">;</span> <span class="c1">// 步骤三 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// cur移动两位,准备下一轮交换 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="2leetcode19删除链表的倒数第n个节点">2.Leetcode19:删除链表的倒数第N个节点 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181140762.png" +loading="lazy" +alt="image-20230218114024717" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中结点的数目为 sz</li> +<li>1 &lt;= sz &lt;= 30</li> +<li>0 &lt;= Node.val &lt;= 100</li> +<li>1 &lt;= n &lt;= sz</li> +</ul> +<p><strong>进阶:你能尝试使用一趟扫描实现吗?</strong></p> +<h4 id="2思路-1">(2)思路 +</h4><p><strong>先抓题意,删除倒数第n个节点,我们很自然的就想到快慢指针法,通过设置一个fast指针和一个slow指针,首先让fast指针移动n步,到达目的节点后,fast指针和slow指针再同时移动,直到fast指针移至尾节点,此时slow指针也刚好指向目标节点,那么这里我们只需要让slow-&gt;next = slow-&gt;next-&gt;next即可完成对目标节点的删除。</strong></p> +<p>同样的对于链表的操作,我们还是采取虚拟头节点的方式进行设计。</p> +<p><strong>&lt;1&gt;首先定义fast指针和slow指针,初始值为虚拟头节点:</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181151708.png" +loading="lazy" +alt="image-20230218115133608" +></p> +<p><strong>&lt;2&gt;fast走n+1步(因为加入了虚拟头节点)</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181152230.png" +loading="lazy" +alt="image-20230218115254196" +></p> +<p><strong>&lt;3&gt;fast和slow同时移动,直到fast指向链表末</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181153041.png" +loading="lazy" +alt="image-20230218115341005" +></p> +<p><strong>&lt;4&gt;删除slow指向的下一个节点</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181154272.png" +loading="lazy" +alt="image-20230218115452233" +></p> +<h4 id="3快慢指针法">(3)快慢指针法 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeNthFromEnd</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">--</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 让fast指向目标节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// fast再提前走一步,因为需要让slow指向删除节点的上一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// ListNode *tmp = slow-&gt;next; C++释放内存的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// slow-&gt;next = tmp-&gt;next; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// delete nth; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode面试题0207链表相交">3.Leetcode面试题02.07:链表相交 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。</strong></p> +<p>图示两个链表在节点 c1 开始相交:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181519759.png" +loading="lazy" +alt="image-20230218151939703" +></p> +<p>题目数据保证整个链式结构中不存在环。</p> +<p>注意,函数返回结果后,链表必须保持其原始结构 。</p> +<p>示例 1:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">3</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;8&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">8</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">2</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">Intersected</span> <span class="n">at</span> <span class="sc">&#39;2&#39;</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:相交节点的值为</span> <span class="mi">2</span> <span class="err">(注意,如果两个链表相交则不能为</span> <span class="mi">0</span><span class="err">)。</span> +</span></span><span class="line"><span class="cl"><span class="err">从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">在</span> <span class="n">A</span> <span class="err">中,相交节点前有</span> <span class="mi">3</span> <span class="err">个节点;在</span> <span class="n">B</span> <span class="err">中,相交节点前有</span> <span class="mi">1</span> <span class="err">个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">intersectVal</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">listA</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="n">listB</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="n">skipA</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">skipB</span> <span class="o">=</span> <span class="mi">2</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:从各自的表头开始算起,链表</span> <span class="n">A</span> <span class="err">为</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="err">,链表</span> <span class="n">B</span> <span class="err">为</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span><span class="err">。</span> +</span></span><span class="line"><span class="cl"><span class="err">由于这两个链表不相交,所以</span> <span class="n">intersectVal</span> <span class="err">必须为</span> <span class="mi">0</span><span class="err">,而</span> <span class="n">skipA</span> <span class="err">和</span> <span class="n">skipB</span> <span class="err">可以是任意值。</span> +</span></span><span class="line"><span class="cl"><span class="err">这两个链表不相交,因此返回</span> <span class="n">null</span> <span class="err">。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>listA 中节点数目为 m</li> +<li>listB 中节点数目为 n</li> +<li>0 &lt;= m, n &lt;= 3 * 104</li> +<li>1 &lt;= Node.val &lt;= 105</li> +<li>0 &lt;= skipA &lt;= m</li> +<li>0 &lt;= skipB &lt;= n</li> +<li>如果 listA 和 listB 没有交点,intersectVal 为 0</li> +<li>如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]</li> +</ul> +<p><strong>进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>根据题意,我们可以有这样一种思路,首先想要找到相交节点,但是可能两个链表的长度不一样,怎么对其是需要考虑的,通过上面的几个示例我们也可以看出,只要让链表1和链表二右对齐即可。</p> +<p>那么在算法中如何实现呢,那么只需要先<strong>分别求出两个链表的长度,然后我们就可以得出两个链表长度的差值n,这个差值就是我们对其的关键</strong>所在啦。</p> +<p><strong>先让长链表移动n步,然后两个链表同时向后移动,并对节点的数值进行判断是否一致,相同的话就是我们所要求解的相交节点了。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181619944.png" +loading="lazy" +alt="image-20230218161958873" +></p> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">getIntersectionNode</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">headA</span><span class="p">,</span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">headB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">lenA</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">lenB</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表A的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenA</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">curB</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 求链表B的长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">lenB</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">headA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">headB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA为最长链表的头,lenA为其长度 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">lenB</span> <span class="o">&gt;</span> <span class="n">lenA</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">lenA</span><span class="p">,</span> <span class="n">lenB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">swap</span> <span class="p">(</span><span class="n">curA</span><span class="p">,</span> <span class="n">curB</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 求长度差 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">lenA</span> <span class="o">-</span> <span class="n">lenB</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 让curA和curB在同一起点上(末尾位置对齐) +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">gap</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 遍历curA 和 curB,遇到相同则直接返回 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">curA</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">curA</span> <span class="o">==</span> <span class="n">curB</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">curA</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">curA</span> <span class="o">=</span> <span class="n">curA</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">curB</span> <span class="o">=</span> <span class="n">curB</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><ul> +<li>时间复杂度:O(n+m)</li> +<li>空间复杂度:O(1)</li> +</ul> +<h2 id="4leetcode142环形链表ii">4.Leetcode142:环形链表II +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/linked-list-cycle-ii</p> +</blockquote> +<h4 id="1题目-3">(1)题目 +</h4><p><strong>给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。</strong></p> +<p><strong>如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。</strong><code>注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。</code></p> +<p><strong>不允许修改链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630702.png" +loading="lazy" +alt="image-20230218163000655" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">1</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第二个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630652.png" +loading="lazy" +alt="image-20230218163029607" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回索引为</span> <span class="mi">0</span> <span class="err">的链表节点</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中有一个环,其尾部连接到第一个节点。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181630718.png" +loading="lazy" +alt="image-20230218163050685" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:返回</span> <span class="n">null</span> +</span></span><span class="line"><span class="cl"><span class="err">解释:链表中没有环。</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围在范围 [0, 104] 内</li> +<li>-105 &lt;= Node.val &lt;= 105</li> +<li>pos 的值为 -1 或者链表中的一个有效索引</li> +</ul> +<p><strong>进阶:你是否可以使用 O(1) 空间解决此题?</strong></p> +<h4 id="2思路-3">(2)思路 +</h4><p>对于这道题的分析,就是为了让我们求解一个链表中是否存在环形链表,如果存在则返回该环形链表的头节点,无环则返回NULL。</p> +<p>对于这道题我们需要解决以下两点:</p> +<ul> +<li>如何判断链表有环</li> +<li>如果有环,怎么找到这个环的入口</li> +</ul> +<p><strong>&lt;1&gt;如何判断链表有环</strong></p> +<p>对于环形链表的判断,我们采取快慢指针法,分别定义fast指针和slow指针,<strong>从头节点出发,fast指针每次移动2个节点,slow指针移动1个节点</strong>,如果fast指针和slow指针在中途相遇,则说明存在环形链表。</p> +<p>由于fast指针走两步,slow指针走一步,那么理论上讲,如果存在环形链表的话是一定存在相遇机会的,动画如下,选自carl大神制作:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181832989.gif" +loading="lazy" +alt="141.环形链表" +></p> +<p><strong>&lt;2&gt;如果有环,怎么找到这个环的入口</strong></p> +<p>既然我们已经有了判断唤醒链表的方式,那么接下来就需要找到环形链表的入口了。</p> +<p>假设从头节点到环形入口的节点数为x,环形入口节点到fast指针与slow指针的相遇节点的节点数为y。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181735057.png" +loading="lazy" +alt="image-20230218173510617" +></p> +<p><strong>当快指针和慢指针相遇时,快指针的走过的节点数不就等于慢指针走过节点数的两倍嘛,只要我们求出快慢指针走过的节点数,就可以联立成一个等式,并且等式中的x值就是我们要求的结果</strong>,那么据此我们可以得出以下结论:</p> +<blockquote> +<p>1.<code>slow指针走过的节点数 = x + y</code></p> +</blockquote> +<blockquote> +<p>2.<code>fast指针走过的节点数 = x + y + n*(y+z)</code> n:代表slow指针进入环形链表后,此时fast指针在环中的循环次数</p> +</blockquote> +<blockquote> +<p>3.得到等式:<code>x + y = x + y + n*(y+z)</code> 此处需要注意:n &gt;= 1,因为在环中fast指针必然是会经历一次循环才有可能被slow指针追上,朋友们可以自己推算一遍</p> +</blockquote> +<blockquote> +<p>4.我们的目标为x,因此化简上式:<code>x = n (y + z) - y</code></p> +</blockquote> +<blockquote> +<p>5.当n等于1时,我们可以得知上式结果为:<code>x = z</code>,这就意味着此时从相遇节点到环形链表的入口节点正好等于从头节点到入口节点的长度。</p> +</blockquote> +<blockquote> +<p>6.根据结论5的分析,我们只需要在fast指针和slow指针相遇时定义一个index指针,同时从头节点也定义一个index2指针,两个指针同时出发,当这两个指针相遇的时候正好就是环形入口的节点</p> +</blockquote> +<p>动画如下:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181833824.gif" +loading="lazy" +alt="142.环形链表II(求入口)" +></p> +<p>上面分析的结论是基于n等于1的,那么当循环此处大于1该如何分析呢?</p> +<p>其实即便n大于1,结果也是一样的,不同的是index1指针会在环中多转(n - 1)圈,然后再遇到index2,建议可以做个示例自己试试。</p> +<h4 id="3代码实现-2">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/** +</span></span></span><span class="line"><span class="cl"><span class="cm"> * Definition for singly-linked list. +</span></span></span><span class="line"><span class="cl"><span class="cm"> * struct ListNode { +</span></span></span><span class="line"><span class="cl"><span class="cm"> * int val; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode *next; +</span></span></span><span class="line"><span class="cl"><span class="cm"> * ListNode(int x) : val(x), next(NULL) {} +</span></span></span><span class="line"><span class="cl"><span class="cm"> * }; +</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span> <span class="o">*</span><span class="n">detectCycle</span><span class="p">(</span><span class="n">ListNode</span> <span class="o">*</span><span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">slow</span> <span class="o">==</span> <span class="n">fast</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index1</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">index2</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">index1</span> <span class="o">!=</span> <span class="n">index2</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">index1</span> <span class="o">=</span> <span class="n">index1</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">index2</span> <span class="o">=</span> <span class="n">index2</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">index2</span><span class="p">;</span> <span class="c1">// 返回环的入口 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="5链表总结">5.链表总结 +</h2><p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302181813815.png" +loading="lazy" +alt="image-20230218181324408" +></p> +<p>图片来源: <a class="link" href="https://programmercarl.com/other/kstar.html" target="_blank" rel="noopener" +>代码随想录知识星球</a>成员:<a class="link" href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412" target="_blank" rel="noopener" +>海螺人</a></p>【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/Fri, 17 Feb 2023 00:00:00 +0000https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/<img src="https://kurisaw.github.io/p/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E9%93%BE%E8%A1%A81%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95%E9%80%92%E5%BD%92%E6%B3%95/cover.jpg" alt="Featured image of post 【数据结构与算法】链表1:移除链表 &设计链表&链表反转(双指针法、递归法)" /><h2 id="今日任务">今日任务 +</h2><ul> +<li> +<p>链表理论基础</p> +</li> +<li> +<p>203.移除链表元素</p> +</li> +<li> +<p>707.设计链表</p> +</li> +<li> +<p>206.反转链表</p> +</li> +</ul> +<h2 id="1链表理论基础">1.链表理论基础 +</h2><h4 id="1什么是链表">(1)什么是链表? +</h4><p><strong>链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。</strong></p> +<p><strong>链表的入口节点称为链表的头节点也就是head。</strong></p> +<h4 id="2链表的类型">(2)链表的类型 +</h4><p>常见的链表类型有以下几种:</p> +<p><strong>&lt;1&gt;单链表</strong></p> +<p>单向链表是一种包含两部分的数据结构,即一个是数据部分(<code>数据域</code>),另一个是地址部分(<code>指针域</code>),其中包含下一个或后继节点的地址。节点中的地址部分也称为<strong>指针</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171142211.png" +loading="lazy" +alt="image-20230217114232162" +></p> +<p>在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为<strong>头指针</strong>。</p> +<p>由于单链表的指针域只保存了下一个节点的地址,因此<strong>在单链表中,只能向前遍历,而不能反向遍历</strong>。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;2&gt;双链表</strong></p> +<p>前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,<strong>每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点</strong>。</p> +<p>这就意味着,双向链表<strong>不仅支持向前查询,还可以向后查询</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171141017.png" +loading="lazy" +alt="image-20230217114149969" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span><span class="lnt">8 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 双向链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>&lt;3&gt;循环链表</strong></p> +<p>循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,<strong>循环链表没有起始节点和结束节点</strong>,我们可以朝任意方向进行遍历(向前或者向后)。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171145612.png" +loading="lazy" +alt="image-20230217114529563" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 循环链表中节点的表示 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> +</span></span><span class="line"><span class="cl"><span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。</p> +<h4 id="3链表的存储方式">(3)链表的存储方式 +</h4><p>前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是<strong>链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。</strong></p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171200336.png" +loading="lazy" +alt="image-20230217120000271" +></p> +<p>在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。</p> +<h4 id="4链表的定义">(4)链表的定义 +</h4><p>给出链表节点的定义:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 单链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">strcut</span> <span class="n">ListNode</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> <span class="c1">//节点上存储的元素 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">//指向下一个节点的指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span><span class="o">:</span> <span class="n">val</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">next</span><span class="p">(</span><span class="nb">NULL</span><span class="p">){}</span> <span class="c1">// 节点的构造函数 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):</p> +<p>1、通过自己定义构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>2、使用默认构造函数初始化节点:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。</p> +<h4 id="5链表的操作">(5)链表的操作 +</h4><p><strong>&lt;1&gt;删除节点</strong></p> +<p>我们以下图为例,目的时删除D节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171424698.png" +loading="lazy" +alt="image-20230217142406253" +></p> +<p>具体操作:</p> +<p>C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要<strong>将C节点的next指针指向E节点就可以了</strong>。</p> +<p>此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。</p> +<p><strong>&lt;2&gt;添加节点</strong></p> +<p>在下图中,我们需要在C节点和D节点中添加一个F节点:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171428029.png" +loading="lazy" +alt="image-20230217142827964" +></p> +<p>添加F节点,只需要<strong>将C节点的next指针指向F节点,同时F节点的next指针指向D节点</strong>,这样就完成了节点的添加。</p> +<h4 id="6性能分析">(6)性能分析 +</h4><p>这里我们将链表和数组做一个对比,详见下图:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171432948.png" +loading="lazy" +alt="image-20230217143205888" +></p> +<ul> +<li>数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。</li> +<li>链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少</li> +</ul> +<h2 id="2leetcode203移除链表元素">2.Leetcode203:移除链表元素 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/remove-linked-list-elements</p> +</blockquote> +<h4 id="1题目">(1)题目 +</h4><p><strong>给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171437824.png" +loading="lazy" +alt="image-20230217143757762" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">6</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">7</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>列表中的节点数目在范围 [0, 104] 内</li> +<li>1 &lt;= Node.val &lt;= 50</li> +<li>0 &lt;= val &lt;= 50</li> +</ul> +<h4 id="2思路">(2)思路 +</h4><p><strong>案例1:</strong></p> +<blockquote> +<p>链表:1-&gt;4-&gt;2-&gt;4 目的:移除元素4</p> +</blockquote> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171440412.png" +loading="lazy" +alt="image-20230217144046231" +></p> +<p>其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171443047.png" +loading="lazy" +alt="image-20230217144342989" +></p> +<p>那么此外我们还需要完成节点4的内存回收工作!</p> +<p><strong>案例二:</strong></p> +<p>由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。</p> +<p>对于链表的操作有两种形式:</p> +<ul> +<li><strong>1.直接使用原来的链表进行删除操作。</strong></li> +<li><strong>2.设置一个虚拟头节点再进行删除操作。</strong></li> +</ul> +<p><strong>&lt;操作1&gt;:直接使用原来的链表进行移除</strong></p> +<p>移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。</p> +<p>那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171456064.png" +loading="lazy" +alt="image-20230217145654957" +></p> +<p>对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。</p> +<p><strong>&lt;操作2&gt;:设置一个虚拟头节点再进行删除操作</strong></p> +<p>如何设置虚拟头节点,<strong>首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4</strong>。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171501788.png" +loading="lazy" +alt="image-20230217150125673" +></p> +<p>具体实现我们详见代码。</p> +<h4 id="3代码实现">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作1实现:直接使用原来的链表进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">head</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> <span class="c1">// 此处需要对旧的头节点进行内存回收 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除非头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 当前节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// cur-&gt;next!= NULL:这里是同样的道理,不可操作空指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>这里需要注意几点:</p> +<ul> +<li>对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错</li> +<li>操作1的关键代码就是下面的这两部分</li> +</ul> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171532596.png" +loading="lazy" +alt="image-20230217153228463" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 操作2实现:设置一个虚拟头节点再进行删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">removeElements</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 设置一个虚拟头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> <span class="c1">// 将虚拟头结点指向head,这样方面后面做删除操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">==</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">head</span> <span class="o">=</span> <span class="n">dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="3leetcode707设计链表">3.Leetcode707:设计链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/design-linked-list</p> +</blockquote> +<h4 id="1题目-1">(1)题目 +</h4><p><strong>设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。</strong></p> +<p><strong>在链表类中实现这些功能:</strong></p> +<ul> +<li>get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。</li> +<li>addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。</li> +<li>addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。</li> +<li>addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。</li> +<li>deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。</li> +</ul> +<p>示例:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span><span class="lnt">3 +</span><span class="lnt">4 +</span><span class="lnt">5 +</span><span class="lnt">6 +</span><span class="lnt">7 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">MyLinkedList</span> <span class="n">linkedList</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MyLinkedList</span><span class="p">();</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtHead</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtTail</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"><span class="n">linkedList</span><span class="p">.</span><span class="n">addAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="c1">//链表变为1-&gt; 2-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回2 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">deleteAtIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//现在链表是1-&gt; 3 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">linkedList</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//返回3 +</span></span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>0 &lt;= index, val &lt;= 1000</li> +<li>请不要使用内置的 LinkedList 库。</li> +<li>get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。</li> +</ul> +<h4 id="2思路-1">(2)思路 +</h4><p>分析题目给出的要求,主要是需要完成以下功能:</p> +<ul> +<li>获取链表第index个节点的值</li> +<li>在链表的最前面插入一个节点</li> +<li>在链表的最后面插入一个节点</li> +<li>在链表第index个节点面前插入一个节点</li> +<li>删除链表的第index个节点</li> +</ul> +<h4 id="3代码实现-1">(3)代码实现 +</h4><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span><span class="lnt">22 +</span><span class="lnt">23 +</span><span class="lnt">24 +</span><span class="lnt">25 +</span><span class="lnt">26 +</span><span class="lnt">27 +</span><span class="lnt">28 +</span><span class="lnt">29 +</span><span class="lnt">30 +</span><span class="lnt">31 +</span><span class="lnt">32 +</span><span class="lnt">33 +</span><span class="lnt">34 +</span><span class="lnt">35 +</span><span class="lnt">36 +</span><span class="lnt">37 +</span><span class="lnt">38 +</span><span class="lnt">39 +</span><span class="lnt">40 +</span><span class="lnt">41 +</span><span class="lnt">42 +</span><span class="lnt">43 +</span><span class="lnt">44 +</span><span class="lnt">45 +</span><span class="lnt">46 +</span><span class="lnt">47 +</span><span class="lnt">48 +</span><span class="lnt">49 +</span><span class="lnt">50 +</span><span class="lnt">51 +</span><span class="lnt">52 +</span><span class="lnt">53 +</span><span class="lnt">54 +</span><span class="lnt">55 +</span><span class="lnt">56 +</span><span class="lnt">57 +</span><span class="lnt">58 +</span><span class="lnt">59 +</span><span class="lnt">60 +</span><span class="lnt">61 +</span><span class="lnt">62 +</span><span class="lnt">63 +</span><span class="lnt">64 +</span><span class="lnt">65 +</span><span class="lnt">66 +</span><span class="lnt">67 +</span><span class="lnt">68 +</span><span class="lnt">69 +</span><span class="lnt">70 +</span><span class="lnt">71 +</span><span class="lnt">72 +</span><span class="lnt">73 +</span><span class="lnt">74 +</span><span class="lnt">75 +</span><span class="lnt">76 +</span><span class="lnt">77 +</span><span class="lnt">78 +</span><span class="lnt">79 +</span><span class="lnt">80 +</span><span class="lnt">81 +</span><span class="lnt">82 +</span><span class="lnt">83 +</span><span class="lnt">84 +</span><span class="lnt">85 +</span><span class="lnt">86 +</span><span class="lnt">87 +</span><span class="lnt">88 +</span><span class="lnt">89 +</span><span class="lnt">90 +</span><span class="lnt">91 +</span><span class="lnt">92 +</span><span class="lnt">93 +</span><span class="lnt">94 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyLinkedList</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 定义链表节点结构体 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">struct</span> <span class="nc">LinkedNode</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span><span class="o">:</span><span class="n">val</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">next</span><span class="p">(</span><span class="k">nullptr</span><span class="p">){}</span> +</span></span><span class="line"><span class="cl"> <span class="p">};</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">MyLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">_size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">){</span> <span class="c1">// 如果--index 就会陷入死循环 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtHead</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_dummyHead</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在链表最后面添加一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtTail</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index大于链表的长度,则返回空 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 如果index小于0,则在头部插入节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">addAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">_size</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">LinkedNode</span><span class="p">(</span><span class="n">val</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">newNode</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">++</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">deleteAtIndex</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">_size</span> <span class="o">||</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span><span class="p">(</span><span class="n">index</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">delete</span> <span class="n">tmp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">_size</span><span class="o">--</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 打印链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">void</span> <span class="nf">printLinkedList</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_size</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">LinkedNode</span><span class="o">*</span> <span class="n">_dummyHead</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h2 id="4leetcode206反转链表">4.Leetcode206:反转链表 +</h2><blockquote> +<p>来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/reverse-linked-list</p> +</blockquote> +<h4 id="1题目-2">(1)题目 +</h4><p><strong>给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。</strong></p> +<p>示例 1:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637917.png" +loading="lazy" +alt="image-20230217163726826" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 2:</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171637025.png" +loading="lazy" +alt="image-20230217163749967" +></p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p>示例 3:</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt">1 +</span><span class="lnt">2 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="err">输入:</span><span class="n">head</span> <span class="o">=</span> <span class="p">[]</span> +</span></span><span class="line"><span class="cl"><span class="err">输出:</span><span class="p">[]</span> +</span></span></code></pre></td></tr></table> +</div> +</div><p><strong>提示:</strong></p> +<ul> +<li>链表中节点的数目范围是 [0, 5000]</li> +<li>-5000 &lt;= Node.val &lt;= 5000</li> +</ul> +<p><strong>进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</strong></p> +<h4 id="2思路-2">(2)思路 +</h4><p>链表的反转,只需要改变next指针的指向即可。</p> +<p><img src="https://raw.githubusercontent.com/kurisaW/picbed/main/img/202302171639640.png" +loading="lazy" +></p> +<h4 id="3双指针法">(3)双指针法 +</h4><p>对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。</p> +<ul> +<li>cur指针,指向链表的头节点</li> +<li>pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址</li> +</ul> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span><span class="p">;</span> <span class="c1">// 作为一个临时节点,保存cur的下一个节点 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为cur +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="c1">// 保存一下 cur的下一个节点,因为接下来要改变cur-&gt;next +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 翻转操作 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// 更新pre 和 cur指针 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">pre</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> <span class="c1">// 返回的是新链表的头节点pre +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><h4 id="4递归法">(4)递归法 +</h4><p>前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有<strong>自前向后递归、以及自后向前递归</strong>两种方法。</p> +<div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span><span class="lnt">19 +</span><span class="lnt">20 +</span><span class="lnt">21 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自前向后 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverse</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">pre</span><span class="p">,</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">){</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">pre</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// pre = cur; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// cur = temp; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span><span class="n">temp</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="nf">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 和双指针法初始化是一样的逻辑 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* cur = head; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// ListNode* pre = NULL; +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">head</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div><div class="highlight"><div class="chroma"> +<table class="lntable"><tr><td class="lntd"> +<pre tabindex="0" class="chroma"><code><span class="lnt"> 1 +</span><span class="lnt"> 2 +</span><span class="lnt"> 3 +</span><span class="lnt"> 4 +</span><span class="lnt"> 5 +</span><span class="lnt"> 6 +</span><span class="lnt"> 7 +</span><span class="lnt"> 8 +</span><span class="lnt"> 9 +</span><span class="lnt">10 +</span><span class="lnt">11 +</span><span class="lnt">12 +</span><span class="lnt">13 +</span><span class="lnt">14 +</span><span class="lnt">15 +</span><span class="lnt">16 +</span><span class="lnt">17 +</span><span class="lnt">18 +</span></code></pre></td> +<td class="lntd"> +<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 递归法:自后向前 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> +</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span> +</span></span><span class="line"><span class="cl"> <span class="n">ListNode</span><span class="o">*</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 边缘条件判断 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// 递归调用,翻转第二个节点开始往后的链表 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">ListNode</span> <span class="o">*</span><span class="n">last</span> <span class="o">=</span> <span class="n">reverseList</span><span class="p">(</span><span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">);</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 翻转头节点与第二个节点的指向 +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="c1">// 此时的 head 节点为尾节点,next 需要指向 NULL +</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">last</span><span class="p">;</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">};</span> +</span></span></code></pre></td></tr></table> +</div> +</div> \ No newline at end of file diff --git "a/tags/\351\223\276\350\241\250/page/1/index.html" "b/tags/\351\223\276\350\241\250/page/1/index.html" new file mode 100644 index 000000000..56da7ee8b --- /dev/null +++ "b/tags/\351\223\276\350\241\250/page/1/index.html" @@ -0,0 +1,2 @@ +https://kurisaw.github.io/tags/%E9%93%BE%E8%A1%A8/ + \ No newline at end of file diff --git a/ts/main.js b/ts/main.js new file mode 100644 index 000000000..91ab33382 --- /dev/null +++ b/ts/main.js @@ -0,0 +1,11 @@ +(()=>{var g=class e{galleryUID;items=[];constructor(t,r=1){if(window.PhotoSwipe==null||window.PhotoSwipeUI_Default==null){console.error("PhotoSwipe lib not loaded.");return}this.galleryUID=r,e.createGallery(t),this.loadItems(t),this.bindClick()}loadItems(t){this.items=[];let r=t.querySelectorAll("figure.gallery-image");for(let i of r){let n=i.querySelector("figcaption"),o=i.querySelector("img"),s={w:parseInt(o.getAttribute("width")),h:parseInt(o.getAttribute("height")),src:o.src,msrc:o.getAttribute("data-thumb")||o.src,el:i};n&&(s.title=n.innerHTML),this.items.push(s)}}static createGallery(t){let r=t.querySelectorAll("img.gallery-image");for(let o of Array.from(r)){let s=o.closest("p");if(!s||!t.contains(s)||(s.textContent.trim()==""&&s.classList.add("no-text"),!s.classList.contains("no-text")))continue;let d=o.parentElement.tagName=="A",m=o,a=document.createElement("figure");if(a.style.setProperty("flex-grow",o.getAttribute("data-flex-grow")||"1"),a.style.setProperty("flex-basis",o.getAttribute("data-flex-basis")||"0"),d&&(m=o.parentElement),m.parentElement.insertBefore(a,m),a.appendChild(m),o.hasAttribute("alt")){let l=document.createElement("figcaption");l.innerText=o.getAttribute("alt"),a.appendChild(l)}if(!d){a.className="gallery-image";let l=document.createElement("a");l.href=o.src,l.setAttribute("target","_blank"),o.parentNode.insertBefore(l,o),l.appendChild(o)}}let i=t.querySelectorAll("figure.gallery-image"),n=[];for(let o of i)n.length?o.previousElementSibling===n[n.length-1]?n.push(o):n.length&&(e.wrap(n),n=[o]):n=[o];n.length>0&&e.wrap(n)}static wrap(t){let r=document.createElement("div");r.className="gallery";let i=t[0].parentNode,n=t[0];i.insertBefore(r,n);for(let o of t)r.appendChild(o)}open(t){let r=document.querySelector(".pswp");new window.PhotoSwipe(r,window.PhotoSwipeUI_Default,this.items,{index:t,galleryUID:this.galleryUID,getThumbBoundsFn:n=>{let o=this.items[n].el.getElementsByTagName("img")[0],s=window.pageYOffset||document.documentElement.scrollTop,c=o.getBoundingClientRect();return{x:c.left,y:c.top+s,w:c.width}}}).init()}bindClick(){for(let[t,r]of this.items.entries())r.el.querySelector("a").addEventListener("click",n=>{n.preventDefault(),this.open(t)})}},b=g;var u={};if(localStorage.hasOwnProperty("StackColorsCache"))try{u=JSON.parse(localStorage.getItem("StackColorsCache"))}catch{u={}}async function S(e,t,r){if(!e)return await Vibrant.from(r).getPalette();if(!u.hasOwnProperty(e)||u[e].hash!==t){let i=await Vibrant.from(r).getPalette();u[e]={hash:t,Vibrant:{hex:i.Vibrant.hex,rgb:i.Vibrant.rgb,bodyTextColor:i.Vibrant.bodyTextColor},DarkMuted:{hex:i.DarkMuted.hex,rgb:i.DarkMuted.rgb,bodyTextColor:i.DarkMuted.bodyTextColor}},localStorage.setItem("StackColorsCache",JSON.stringify(u))}return u[e]}var D=(e,t=500)=>{e.classList.add("transiting"),e.style.transitionProperty="height, margin, padding",e.style.transitionDuration=t+"ms",e.style.height=e.offsetHeight+"px",e.offsetHeight,e.style.overflow="hidden",e.style.height="0",e.style.paddingTop="0",e.style.paddingBottom="0",e.style.marginTop="0",e.style.marginBottom="0",window.setTimeout(()=>{e.classList.remove("show"),e.style.removeProperty("height"),e.style.removeProperty("padding-top"),e.style.removeProperty("padding-bottom"),e.style.removeProperty("margin-top"),e.style.removeProperty("margin-bottom"),e.style.removeProperty("overflow"),e.style.removeProperty("transition-duration"),e.style.removeProperty("transition-property"),e.classList.remove("transiting")},t)},q=(e,t=500)=>{e.classList.add("transiting"),e.style.removeProperty("display"),e.classList.add("show");let r=e.offsetHeight;e.style.overflow="hidden",e.style.height="0",e.style.paddingTop="0",e.style.paddingBottom="0",e.style.marginTop="0",e.style.marginBottom="0",e.offsetHeight,e.style.transitionProperty="height, margin, padding",e.style.transitionDuration=t+"ms",e.style.height=r+"px",e.style.removeProperty("padding-top"),e.style.removeProperty("padding-bottom"),e.style.removeProperty("margin-top"),e.style.removeProperty("margin-bottom"),window.setTimeout(()=>{e.style.removeProperty("height"),e.style.removeProperty("overflow"),e.style.removeProperty("transition-duration"),e.style.removeProperty("transition-property"),e.classList.remove("transiting")},t)},B=(e,t=500)=>window.getComputedStyle(e).display==="none"?q(e,t):D(e,t);function v(){let e=document.getElementById("toggle-menu");e&&e.addEventListener("click",()=>{document.getElementById("main-menu").classList.contains("transiting")||(document.body.classList.toggle("show-menu"),B(document.getElementById("main-menu"),300),e.classList.toggle("is-active"))})}function N(e,t,r){var i=document.createElement(e);for(let n in t)if(n&&t.hasOwnProperty(n)){let o=t[n];n=="dangerouslySetInnerHTML"?i.innerHTML=o.__html:o===!0?i.setAttribute(n,n):o!==!1&&o!=null&&i.setAttribute(n,o.toString())}for(let n=2;n{this.isDark()?this.currentScheme="light":this.currentScheme="dark",this.setBodyClass(),this.currentScheme==this.systemPreferScheme&&(this.currentScheme="auto"),this.saveScheme()})}isDark(){return this.currentScheme=="dark"||this.currentScheme=="auto"&&this.systemPreferScheme=="dark"}dispatchEvent(t){let r=new CustomEvent("onColorSchemeChange",{detail:t});window.dispatchEvent(r)}setBodyClass(){this.isDark()?document.documentElement.dataset.scheme="dark":document.documentElement.dataset.scheme="light",this.dispatchEvent(document.documentElement.dataset.scheme)}getSavedScheme(){let t=localStorage.getItem(this.localStorageKey);return t=="light"||t=="dark"||t=="auto"?t:"auto"}bindMatchMedia(){window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",t=>{t.matches?this.systemPreferScheme="dark":this.systemPreferScheme="light",this.setBodyClass()})}},E=y;function p(e){let t;return()=>{t&&window.cancelAnimationFrame(t),t=window.requestAnimationFrame(()=>e())}}var O=".article-content h1[id], .article-content h2[id], .article-content h3[id], .article-content h4[id], .article-content h5[id], .article-content h6[id]",T="#TableOfContents",L="#TableOfContents li",k="active-class";function V(e,t){let r=e.querySelector("a").offsetHeight,i=e.offsetTop-t.offsetHeight/2+r/2-t.offsetTop;i<0&&(i=0),t.scrollTo({top:i,behavior:"smooth"})}function U(e){let t={};return e.forEach(r=>{let n=r.querySelector("a").getAttribute("href");n.startsWith("#")&&(t[n.slice(1)]=r)}),t}function C(e){let t=[];return e.forEach(r=>{t.push({id:r.id,offset:r.offsetTop})}),t.sort((r,i)=>r.offset-i.offset),t}function M(){let e=document.querySelectorAll(O);if(!e){console.warn("No header matched query",e);return}let t=document.querySelector(T);if(!t){console.warn("No toc matched query",T);return}let r=document.querySelectorAll(L);if(!r){console.warn("No navigation matched query",L);return}let i=C(e),n=!1;t.addEventListener("mouseenter",p(()=>n=!0)),t.addEventListener("mouseleave",p(()=>n=!1));let o,s=U(r);function c(){let m=document.documentElement.scrollTop||document.body.scrollTop,a;i.forEach(f=>{m>=f.offset-20&&(a=document.getElementById(f.id))});let l;a&&(l=s[a.id]),a&&!l?console.debug("No link found for section",a):l!==o&&(o&&o.classList.remove(k),l&&(l.classList.add(k),n||V(l,t)),o=l)}window.addEventListener("scroll",p(c));function d(){i=C(e),c()}window.addEventListener("resize",p(d))}var $="a[href]";function P(){document.querySelectorAll($).forEach(e=>{e.getAttribute("href").startsWith("#")&&e.addEventListener("click",r=>{r.preventDefault();let i=decodeURI(e.getAttribute("href").substring(1)),n=document.getElementById(i),o=n.getBoundingClientRect().top-document.documentElement.getBoundingClientRect().top;window.history.pushState({},"",e.getAttribute("href")),scrollTo({top:o,behavior:"smooth"})})})}var x={init:()=>{v();let e=document.querySelector(".article-content");e&&(new b(e),P(),M());let t=document.querySelector(".article-list--tile");t&&new IntersectionObserver(async(s,c)=>{s.forEach(d=>{if(!d.isIntersecting)return;c.unobserve(d.target),d.target.querySelectorAll("article.has-image").forEach(async a=>{let l=a.querySelector("img"),f=l.src,H=l.getAttribute("data-key"),I=l.getAttribute("data-hash"),A=a.querySelector(".article-details"),h=await S(H,I,f);A.style.background=` + linear-gradient(0deg, + rgba(${h.DarkMuted.rgb[0]}, ${h.DarkMuted.rgb[1]}, ${h.DarkMuted.rgb[2]}, 0.5) 0%, + rgba(${h.Vibrant.rgb[0]}, ${h.Vibrant.rgb[1]}, ${h.Vibrant.rgb[2]}, 0.75) 100%)`})})}).observe(t);let r=document.querySelectorAll(".article-content div.highlight"),i="Copy",n="Copied!";r.forEach(o=>{let s=document.createElement("button");s.innerHTML=i,s.classList.add("copyCodeButton"),o.appendChild(s);let c=o.querySelector("code[data-lang]");c&&s.addEventListener("click",()=>{navigator.clipboard.writeText(c.textContent).then(()=>{s.textContent=n,setTimeout(()=>{s.textContent=i},1e3)}).catch(d=>{alert(d),console.log("Something went wrong",d)})})}),new E(document.getElementById("dark-mode-toggle"))}};window.addEventListener("load",()=>{setTimeout(function(){x.init()},0)});window.Stack=x;window.createElement=w;})(); +/*! +* Hugo Theme Stack +* +* @author: Jimmy Cai +* @website: https://jimmycai.com +* @link: https://github.com/CaiJimmy/hugo-theme-stack +*/ diff --git a/ts/search.js b/ts/search.js new file mode 100644 index 000000000..e22d8ef4c --- /dev/null +++ b/ts/search.js @@ -0,0 +1 @@ +(()=>{var m={"&":"&","<":"<",">":">",'"':""","\u2026":"…"};function T(l){return m[l]||l}function d(l){return l.replace(/[&<>"]/g,T)}function w(l){return l.replace(/[.*+\-?^${}()|[\]\\]/g,"\\$&")}var g=class l{data;form;input;list;resultTitle;resultTitleTemplate;constructor({form:t,input:e,list:r,resultTitle:o,resultTitleTemplate:n}){this.form=t,this.input=e,this.list=r,this.resultTitle=o,this.resultTitleTemplate=n,this.handleQueryString(),this.bindQueryStringChange(),this.bindSearchForm()}static processMatches(t,e,r=!0,o=140,n=20){e.sort((a,s)=>a.start-s.start);let h=0,i=0,c=0,u=[];for(;hi?(u.push(`${d(t.substring(i,i+n))} [...] `),u.push(`${d(t.substring(a.start-n,a.start))}`),c+=n*2):(u.push(d(t.substring(i,a.start))),c+=a.start-i);let s=h+1,p=a.end;for(;s${d(t.substring(a.start,p))}`),c+=p-a.start,h=s,i=p,r&&c>o)break}if(i(i[h]=w(n),n.trim()!=="")).join("|"),"gi");for(let n of e){let h=[],i=[],c={...n,preview:"",matchCount:0},u=n.content.matchAll(o);for(let s of Array.from(u))i.push({start:s.index,end:s.index+s[0].length});let a=n.title.matchAll(o);for(let s of Array.from(a))h.push({start:s.index,end:s.index+s[0].length});h.length>0&&(c.title=l.processMatches(c.title,h,!1)),i.length>0?c.preview=l.processMatches(c.content,i):c.preview=d(c.content.substring(0,140)),c.matchCount=h.length+i.length,c.matchCount>0&&r.push(c)}return r.sort((n,h)=>h.matchCount-n.matchCount)}async doSearch(t){let e=performance.now(),r=await this.searchKeywords(t);this.clear();for(let n of r)this.list.append(l.render(n));let o=performance.now();this.resultTitle.innerText=this.generateResultTitle(r.length,((o-e)/1e3).toPrecision(1))}generateResultTitle(t,e){return this.resultTitleTemplate.replace("#PAGES_COUNT",t).replace("#TIME_SECONDS",e)}async getData(){if(!this.data){let t=this.form.dataset.json;this.data=await fetch(t).then(r=>r.json());let e=new DOMParser;for(let r of this.data)r.content=e.parseFromString(r.content,"text/html").body.innerText}return this.data}bindSearchForm(){let t="",e=r=>{r.preventDefault();let o=this.input.value.trim();if(l.updateQueryString(o,!0),o==="")return t="",this.clear();t!==o&&(t=o,this.doSearch(o.split(" ")))};this.input.addEventListener("input",e),this.input.addEventListener("compositionend",e)}clear(){this.list.innerHTML="",this.resultTitle.innerText=""}bindQueryStringChange(){window.addEventListener("popstate",t=>{this.handleQueryString()})}handleQueryString(){let e=new URL(window.location.toString()).searchParams.get("keyword");this.input.value=e,e?this.doSearch(e.split(" ")):this.clear()}static updateQueryString(t,e=!1){let r=new URL(window.location.toString());t===""?r.searchParams.delete("keyword"):r.searchParams.set("keyword",t),e?window.history.replaceState("","",r.toString()):window.history.pushState("","",r.toString())}static render(t){return createElement("article",null,createElement("a",{href:t.permalink},createElement("div",{class:"article-details"},createElement("h2",{class:"article-title",dangerouslySetInnerHTML:{__html:t.title}}),createElement("section",{class:"article-preview",dangerouslySetInnerHTML:{__html:t.preview}})),t.image&&createElement("div",{class:"article-image"},createElement("img",{src:t.image,loading:"lazy"}))))}};window.addEventListener("load",()=>{setTimeout(function(){let l=document.querySelector(".search-form"),t=l.querySelector("input"),e=document.querySelector(".search-result--list"),r=document.querySelector(".search-result--title");new g({form:l,input:t,list:e,resultTitle:r,resultTitleTemplate:window.searchResultTitleTemplate})},0)});var f=g;})();